469,926 Members | 1,824 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,926 developers. It's quick & easy.

RegExp for hyphen to camelCase?


I'm messing with getPropertyValue (Mozilla et al) and currentStyle (IE)
and have a general function (slightly modified from one originally
posted by Steve van Dongen) for getting style properties:

function GetCurrentStyle( el, prop ) {
if ( window.getComputedStyle ) {
// Mozilla et al
return window.getComputedStyle(el, '').getPropertyValue(prop) );
} // IE5+
else if ( el.currentStyle ) {
return el.currentStyle[prop];
} // IE4
else if ( el.style ) {
return el.style[prop];
}
}

If property names have no hyphen (e.g. width, height) then all is fine.
But with hyphenated names (e.g. margin-right, border-top) Mozilla
wants them unmodified and IE wants them camelCased (marginRight, borderTop).

Is there a simple RegExp that will camelCase hyphenated strings? I can
do it with a loop and string operations but would prefer to use a single
RegExp if possible.

The following works fine using substring (for s having 0 or more
hyphens) but is there a simpler way?

function toCamel ( s ) {
s = s.split('-');
var i=0, j=s.length;
while ( ++i < j ) {
s[0] += s[i].substring(0,1).toUpperCase() + s[i].substring(1);
}
return s[0];
}

I've tried using RegExp but can't get a simple expression without
looping - property names have up to 3 (or more? three-d-light-shadow)
hyphens, a RegExp with global flag should be possible.

Any suggestions?

--
Rob
Jul 23 '05 #1
20 3278
VK


RobG wrote:
I'm messing with getPropertyValue (Mozilla et al) and currentStyle (IE)
and have a general function (slightly modified from one originally
posted by Steve van Dongen) for getting style properties:

function GetCurrentStyle( el, prop ) {
if ( window.getComputedStyle ) {
// Mozilla et al
return window.getComputedStyle(el, '').getPropertyValue(prop) );
} // IE5+
else if ( el.currentStyle ) {
return el.currentStyle[prop];
} // IE4
else if ( el.style ) {
return el.style[prop];
}
}

If property names have no hyphen (e.g. width, height) then all is fine.
But with hyphenated names (e.g. margin-right, border-top) Mozilla
wants them unmodified and IE wants them camelCased (marginRight, borderTop).

Is there a simple RegExp that will camelCase hyphenated strings? I can
do it with a loop and string operations but would prefer to use a single
RegExp if possible.

The following works fine using substring (for s having 0 or more
hyphens) but is there a simpler way?

function toCamel ( s ) {
s = s.split('-');
var i=0, j=s.length;
while ( ++i < j ) {
s[0] += s[i].substring(0,1).toUpperCase() + s[i].substring(1);
}
return s[0];
}

I've tried using RegExp but can't get a simple expression without
looping - property names have up to 3 (or more? three-d-light-shadow)
hyphens, a RegExp with global flag should be possible.

Any suggestions?

--

The pattern search would be simple:

var re = /(-)([a-z])/g;

hyphenString.replace(re,"$2");

This would transform "a-b-c" to "abc"

Unfortunately back to NN4 they have forgotten to include in
JavaScript's RegExp the case transformation sequences (\u and \U). And
so far no one bothered to fix it. So there is no way to transform
"a-b-c" to "aBC" other than using .exec method, pass through all
matches and apply toUpperCase() with string re-assemply each time.

In this case the old charAt/substring method *much* more time/ressource
effective :-(

Jul 23 '05 #2
I would agree with VK's comments.

Taking from both your comments you could try this at least:-

var s="three-d-light-shadow";
var r=/(-)([a-z])/g;
s=s.replace(r,function(a,b,c){return c.toUpperCase();});
alert(s);

Jul 23 '05 #3
fox


RobG wrote:

I'm messing with getPropertyValue (Mozilla et al) and currentStyle (IE)
and have a general function (slightly modified from one originally
posted by Steve van Dongen) for getting style properties:

function GetCurrentStyle( el, prop ) {
if ( window.getComputedStyle ) {
// Mozilla et al
return window.getComputedStyle(el, '').getPropertyValue(prop) );
} // IE5+
else if ( el.currentStyle ) {
return el.currentStyle[prop];
} // IE4
else if ( el.style ) {
return el.style[prop];
}
}

If property names have no hyphen (e.g. width, height) then all is fine.
But with hyphenated names (e.g. margin-right, border-top) Mozilla wants
them unmodified and IE wants them camelCased (marginRight, borderTop).

Is there a simple RegExp that will camelCase hyphenated strings? I can
do it with a loop and string operations but would prefer to use a single
RegExp if possible.

The following works fine using substring (for s having 0 or more
hyphens) but is there a simpler way?

function toCamel ( s ) {
s = s.split('-');
var i=0, j=s.length;
while ( ++i < j ) {
s[0] += s[i].substring(0,1).toUpperCase() + s[i].substring(1);
}
return s[0];
}

I've tried using RegExp but can't get a simple expression without
looping - property names have up to 3 (or more? three-d-light-shadow)
hyphens, a RegExp with global flag should be possible.

Any suggestions?


function
toCamel(s)
{
var re = /(-)(\w)/g;

return s.replace(re,
function(fullmatch,paren1,paren2)
{
return paren2.toUpperCase();
});
}

Jul 23 '05 #4
VK
> var s="three-d-light-shadow";
var r=/(-)([a-z])/g;
s=s.replace(r,function(a,b,c){return c.toUpperCase();});
alert(s);


That's an absolutely cool twist!
Flushing substring !

Jul 23 '05 #5
It does enable you to be quite concise.

Oddly though, I have found that if you use this type of technique on
very large strings, it actually becomes much more inefficient than
ordinary String concatenation or Array joining, by quite a margin. For
a 200k string, String concatenation is about 10x faster. But for small
Strings can be quite useful.

Jul 23 '05 #6
VK
> Oddly though, I have found that if you use this type of technique on
very large strings, it actually becomes much more inefficient than
ordinary String concatenation or Array joining, by quite a margin. For
a 200k string, String concatenation is about 10x faster.


it's not so odd because regexp's are very resource intensive. So on big
texts it takes *a lot*. In some serious implementations of regexp's
there is study() method to "prepare" a large text for regexp
processing.

IE introduced re.compile() method to convert static regexp to binary
code for maximum speed. Did you try that?

Jul 23 '05 #7
>it's not so odd because regexp's are very resource intensive. So on big
texts it takes *a lot*.
I can see how that would be.
I suppose jumping out of the process to call a function will not help
either.
IE introduced re.compile() method to convert static regexp to binary
code for maximum speed. Did you try that?


No I didn't. I'll give it a try. Thanks.

Jul 23 '05 #8
Baconbutty wrote:
I would agree with VK's comments.

Taking from both your comments you could try this at least:-

var s="three-d-light-shadow";
var r=/(-)([a-z])/g;
s=s.replace(r,function(a,b,c){return c.toUpperCase();});
alert(s);


Cool, unfortunately Safari doesn't like it, returning:

threefunction (a, b, c)
{
return c.toUpperCase();
}function (a, b, c)
{
return c.toUpperCase();
}ightfunction (a, b, c)
{
return c.toUpperCase();
}hadow

It is returning the function body rather than the result - similarly
for Fox's suggestion.

So thanks, but I'll have to stick with looping for now. Hopefully
style property names will never reach 200k ;-)
--
Rob
Jul 23 '05 #9
On 21/07/2005 12:39, RobG wrote:
Baconbutty wrote:
[Use a function argument]
Cool, unfortunately Safari doesn't like it, [...]

It is returning the function body rather than the result - similarly for
Fox's suggestion.
So will IE5 and earlier as they don't support function arguments, and
Opera 6 won't perform a replacement at all (a no-op).
So thanks, but I'll have to stick with looping for now. [...]


It takes about 2KB to replace the replace method. :)

Mike

--
Michael Winter
Prefix subject with [News] before replying by e-mail.
Jul 23 '05 #10
> Cool, unfortunately Safari doesn't like it,
Will IE5 and earlier as they don't support function arguments
Opera 6 won't perform a replacement at all
Thats a shame. It is in the ECMA spec I think, but that is of course
no guarantee that it is implemented everywhere. .
It takes about 2KB to replace the replace method. :)


Perhaps the challenge then is to come up with the most concise
alternative. A starter:-

var a=s.split(""); var b=[]; var j=a.length; var i=0;
do {b[b.length]=(a[i]=="-")?a[++i].toUpperCase():a[i];}while(++i<j)

Jul 23 '05 #11


RobG wrote:

function GetCurrentStyle( el, prop ) {
if ( window.getComputedStyle ) {
// Mozilla et al
return window.getComputedStyle(el, '').getPropertyValue(prop) );
} // IE5+
else if ( el.currentStyle ) {
return el.currentStyle[prop];
} // IE4
else if ( el.style ) {
return el.style[prop];
}
}

If property names have no hyphen (e.g. width, height) then all is fine.
But with hyphenated names (e.g. margin-right, border-top) Mozilla wants
them unmodified and IE wants them camelCased (marginRight, borderTop).


getComputedStyle is supposed to return an object implementing the
CSSStyleDeclaration interface but that interface can optionally be
casted to the CSS2Properties interface which then allows accessing CSS
properties the same way you do with element.style in browsers e.g.
element.style.cssPropertyName
so in Mozilla and Opera you can do
return window.getComputedStyle(el, '')[prop]
if the CSS property name is passed in in camel case (e.g.
'backgroundColor', 'marginRight').
Could you test whether Safari allows that too?

--

Martin Honnen
http://JavaScript.FAQTs.com/
Jul 23 '05 #12
On 21/07/2005 14:10, Martin Honnen wrote:

[snip]
so in Mozilla and Opera you can do
return window.getComputedStyle(el, '')[prop]
You could but the global object has never been defined as an instance of
the AbstractView interface. I would use the slightly longer, but
better defined route through the document object:

document.defaultView.getComputedStyle(...)
if the CSS property name is passed in in camel case (e.g.
'backgroundColor', 'marginRight').
Though you should be careful as there is an exception to the case
conversion pattern: float becomes cssFloat.
Could you test whether Safari allows that too?


Neither Safari nor Konqueror support the getComputedStyle method. Though
it exists as a property of the defaultView object in Konqueror, it
always returns null.

Mike

--
Michael Winter
Prefix subject with [News] before replying by e-mail.
Jul 23 '05 #13


Michael Winter wrote:
On 21/07/2005 14:10, Martin Honnen wrote:
so in Mozilla and Opera you can do
return window.getComputedStyle(el, '')[prop]

You could but the global object has never been defined as an instance of
the AbstractView interface. I would use the slightly longer, but better
defined route through the document object:

document.defaultView.getComputedStyle(...)


Right, I was mainly following Rob's code and only changing the part
after the getComputedStyle. I have myself pointed out that
document.defaultView and window don't have to be the same as far as the
W3C DOM says but as far as Mozilla goes Brendan Eich himself said the
current behaviour is not going to be changed:
<http://groups-beta.google.com/group/netscape.public.mozilla.dom/msg/aa219bf41334c22e?hl=en&>
And the current WHAT WG drafts also try to ensure that the current
praxis that browsers implement document.defaultView as the window object
becomes standardized:
<http://www.whatwg.org/specs/web-apps/current-work/#documentwindow>
so it seems pretty safe to do window.getComputedStyle.

Neither Safari nor Konqueror support the getComputedStyle method. Though
it exists as a property of the defaultView object in Konqueror, it
always returns null.


Ouch, one more case for not only checking for the existance of a method
in the DOM but to check for the result too.

--

Martin Honnen
http://JavaScript.FAQTs.com/
Jul 23 '05 #14
"Baconbutty" <ju****@baconbutty.com> writes:
Perhaps the challenge then is to come up with the most concise
alternative. A starter:-

var a=s.split(""); var b=[]; var j=a.length; var i=0;
do {b[b.length]=(a[i]=="-")?a[++i].toUpperCase():a[i];}while(++i<j)


Overkill (mainly splitting the string into a character array and
looking at each char, not the total size of the snippet). Also
remember to join "b" afterwards.

Anyway:

var p=s.split("-"),i=p.length;
while(--i){p[i]=p[i].charAt(0).toUpperCase()+p[i].substring(1);}
s=p.join("");

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 23 '05 #15
Michael Winter <m.******@blueyonder.co.uk> writes:
It takes about 2KB to replace the replace method. :)


If you don't need full generality, or efficiency, you can do something
like:
---
function replace(string, regexp, func) {
var match, lastMatchEnd=0, res = [];
while((match = regexp.exec(string))) {
var matchString = match[0];
var index = string.indexOf(matchString, lastMatchEnd);
res.push(string.substring(lastMatchEnd, index));
var repl = func.apply(null, match.concat([index, string]));
res.push(String(repl));
lastMatchEnd = index + matchString.length;
}
res.push(string.substring(lastMatchEnd));
return res.join("");
}
---
It should do approximatly the same as string.replace(regexp,func),
assuming that regexp.global is true, in somewhat less than 2K :)

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 23 '05 #16
On 21/07/2005 23:06, Lasse Reichstein Nielsen wrote:
Michael Winter <m.******@blueyonder.co.uk> writes:
It takes about 2KB to replace the replace method. :)
If you don't need full generality, or efficiency, you can do something
like:
---
function replace(string, regexp, func) {
var match, lastMatchEnd=0, res = [];
while((match = regexp.exec(string))) {
var matchString = match[0];
var index = string.indexOf(matchString, lastMatchEnd);


Have you found the index property of the returned array to be unreliable?
res.push(string.substring(lastMatchEnd, index));
If replacement of the replace method is necessary, push...
var repl = func.apply(null, match.concat([index, string]));
....and apply will probably need to be supplied as well (part of my 2KB).
For example, with IE5.

[snip]
assuming that regexp.global is true [...]


The global flag would seem to be a pain; non-existent in IE5 and always
false in early Opera. In those browsers you can match against the string
representation of that object, but I seem to recall Richard saying that
not all browsers would produce a useful value.

[mini rant]
I know that the replace method isn't usually /necessary/ to accomplish a
task, but it would be nice to be able to just call it knowing the darn
thing will work as expected. Oh well, such is browser scripting...
[/mini rant]

Mike

--
Michael Winter
Prefix subject with [News] before replying by e-mail.
Jul 23 '05 #17
Michael Winter <m.******@blueyonder.co.uk> writes:
var index = string.indexOf(matchString, lastMatchEnd);
Have you found the index property of the returned array to be unreliable?


Nope, just haven't found it at all :)
If replacement of the replace method is necessary, push... ...and apply will probably need to be supplied as well (part of my
2KB). For example, with IE5.
True. Push is easily replacable:
foo.push(value); ==> foo[foo.length]=value;
but apply is *hard*. It's one of the few valid uses of "eval" that I
have found. However, we don't need to follow the argument structure
of String.prototype.replace as strictly, so it might be better to
use a fixed argument format, e.g. all captures in one array argument:
var repl = func(match[0], match.slice(1), index, string);
[snip]
assuming that regexp.global is true [...]


The global flag would seem to be a pain; non-existent in IE5 and
always false in early Opera.

....

In this case, it's not really the flag itself that is important, but
the behavior of the RegExp on successive calls that it implies.
If that fails, then you will definitly need more plumbing.
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 23 '05 #18
> Overkill

On reflection it is.
Also remember to join "b" afterwards.


Oops, fogot to cut and paste that :-o

Jul 23 '05 #19
Martin Honnen wrote:


Michael Winter wrote:
On 21/07/2005 14:10, Martin Honnen wrote:
so in Mozilla and Opera you can do
return window.getComputedStyle(el, '')[prop]

Thanks, I'll use that. No need to add humps of unnecessary code (that
was a really bad pun).

You could but the global object has never been defined as an instance
of the AbstractView interface. I would use the slightly longer, but
better defined route through the document object:

document.defaultView.getComputedStyle(...)

Right, I was mainly following Rob's code and only changing the part
after the getComputedStyle. I have myself pointed out that
document.defaultView and window don't have to be the same as far as the
W3C DOM says but as far as Mozilla goes Brendan Eich himself said the
current behaviour is not going to be changed:
<http://groups-beta.google.com/group/netscape.public.mozilla.dom/msg/aa219bf41334c22e?hl=en&>

And the current WHAT WG drafts also try to ensure that the current
praxis that browsers implement document.defaultView as the window object
becomes standardized:
<http://www.whatwg.org/specs/web-apps/current-work/#documentwindow>
so it seems pretty safe to do window.getComputedStyle.

Neither Safari nor Konqueror support the getComputedStyle method.
Though it exists as a property of the defaultView object in Konqueror,
it always returns null.

Ouch, one more case for not only checking for the existance of a method
in the DOM but to check for the result too.


Agggh, I tested it in Safari (1.0.3) and surprise, Mike is right.
(typeof window.getComputedStyle) returns undefined. Using the code as
posted, Safari falls through to the IE 4 test - el.style - which is
undesirable.

I guess the bottom line is that if you want reliable information about
current element style, everything needs to be applied either inline or
as an element property. Getting CSS style stuff is not reliable.
--
Rob
Jul 23 '05 #20
I found this thread Googling about looking for more on 'getComputedStyle'. I also found this neat function for it which I have spruced up a bit:
Expand|Select|Wrap|Line Numbers
  1. function getElementStyle(elemID, styleProp, isID) {
  2.     var elem = elemID
  3.     if (isID)
  4.     elem = document.all? document.all[elemID] : document.getElementById(elemID);
  5.     if (elem.currentStyle) {
  6.         return elem.currentStyle[styleProp];
  7.     } else if (window.getComputedStyle) {
  8.         var compStyle = window.getComputedStyle(elem, "");
  9.         return compStyle.getPropertyValue(deCamel(styleProp));
  10.     }
  11.     return "";
  12. }
  13.  
  14. function deCamel (string){
  15. var newString=''
  16. for (var i_tem = 0; i_tem < string.length; i_tem++){
  17. if (string.charCodeAt(i_tem)>=65&&string.charCodeAt(i_tem)<=90)
  18. newString+='-'+string.charAt(i_tem).toLowerCase()
  19. else
  20. newString+=string.charAt(i_tem)
  21. }
  22. return newString
  23. }
So as to be on topic, I also made an 'enCamel' function:
Expand|Select|Wrap|Line Numbers
  1. function enCamel (string){
  2. var newString=''
  3. for (var i_tem = 0; i_tem < string.length; i_tem++){
  4. if (string.charAt(i_tem)=='-'){
  5. newString+=string.charAt(i_tem+1).toUpperCase()
  6. i_tem++
  7. }
  8. else
  9. newString+=string.charAt(i_tem)
  10. }
  11. return newString
  12. }
Withstanding the limitations discussed in the previous posts in this thread, these are still valid methods if used only to deal with specific targeted browsers. For example, when making a script that fades text on Mozilla and IE, a background must be supplied in IE if it doesn't exist. The effect only works in browsers supporting filters, -moz-opacity, or opacity, degrading well in others. For the latter two types the background is a non-issue, for IE, it must be present, if not it can be found and applied by walking up the document tree until one is encountered. An IE specific solution to an IE specific problem.
Sep 27 '05 #21

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by John Benson | last post: by
5 posts views Thread by Syed Ali | last post: by
27 posts views Thread by The Bicycling Guitarist | last post: by
13 posts views Thread by Matt | last post: by
12 posts views Thread by Dag Sunde | last post: by
3 posts views Thread by durumdara | last post: by
5 posts views Thread by gentsquash | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.