13

I have a string in this form:

url("http://www.example.com/imgs/backgrounds/bg80.jpg") repeat scroll 10% 0% transparent

This is from a CSS styling for a certain element that at the moment isn't visible on the page. What I need to do is preload that background image, but to do this I need it's URL, and I'm trying to write a regular expression find it.

I know the http://www.example.com/imgs/backgrounds/ part remains constant, the only thing changing is the image name itself, which can end with either .jpg or .png.

This was one attempt:

(http:\/\/www.example.com\/imgs\/backgrounds\/)[\w\.\-]*

The problem with this being that only the http://www.example.com/imgs/backgrounds/ part was being picked up. So I tried this, but this doesn't work at all!

(http:\/\/www.example.com\/imgs\/backgrounds\/)[\w\.\-]*(.jpg|.png)

What am I doing wrong? Thank you for any help!

1
  • (http:\/\/www.example.com\/imgs\/backgrounds\/[\w-]+\.(jpg|png))? Commented Dec 31, 2013 at 12:30

5 Answers 5

29

A background url can have ' or " or none around the url inside the parenthesis

Valid urls

  • url("http://www.example.com/imgs/backgrounds/bg80.jpg")
  • url('http://www.example.com/imgs/backgrounds/bg80.jpg')
  • url(http://www.example.com/imgs/backgrounds/bg80.jpg)

So for a generic solution you could use

var background = 'url("http://www.example.com/imgs/backgrounds/bg80.jpg") repeat scroll 10% 0% transparent',
    reg = /(?:\(['"]?)(.*?)(?:['"]?\))/,
    extracterUrl = reg.exec(background)[1];
Sign up to request clarification or add additional context in comments.

9 Comments

This should be the accepted answer; it's a single regexp that extracts urls from all possible declaration formats, without the need to .replace() anything.
Shouldn't the regex contain the "url" word as well?
@UdoG no because we are trying to extract the actual URL string. And since there are very specific rules about how the properties of the background property are constructed there can be nothing else inside parenthesis (which is what we use to identify the url)
What's the pipe character doing in the character enumeration? That's wrong, isn't it?
Why is it wrong to include the word "url"? It obviously wouldn't affect what the group matches on.
|
17

Just capture anything between ( and )

var url = str.match(/\((.*?)\)/)[1].replace(/('|")/g,'');

var image = new Image();
image.src = url;

FIDDLE

10 Comments

better make the " be "|' and make it optional as well.. (for generic use)
Ah... much simpler! Just a curiosity - what is the ? doing?
@GabyakaG.Petrioli - my regex foo is so poor, I don't know how?
@Sean ? means a lazy match. Match as little characters as possible
I had to add url, like attr.match(/url((.*?))/)[1].replace(/('|")/g,'') otherwise, there was a color(0,0,0,0) that the parens only reg exp was picking up on. Sharing in case anyone is also in that predicament.
|
4

I feel like Gaby's answer is almost correct, but according to this answer, unquoted CSS URLs can include escaped characters (ex: background-image: url(http://foobar.com?\'\() is a valid way to load a background image with the url http://foobar.com?'). A more accurate expression for capturing all URLs in a stylesheet (tests here):

/[:,\s]\s*url\s*\(\s*(?:'(\S*?)'|"(\S*?)"|((?:\\\s|\\\)|\\\"|\\\'|\S)*?))\s*\)/gi

var urlMatchingRegex = /[:,\s]\s*url\s*\(\s*(?:'(\S*?)'|"(\S*?)"|((?:\\\s|\\\)|\\\"|\\\'|\S)*?))\s*\)/gi;

myStylesheetString.replace(urlMatchingRegex, function(fullMatch, url) { 
  //Replacement handler 
});

Comments

1

I just do it now and I get to this page so I think so my pattern its simply and absolutely:

/url(?:\([\'"\s]?)((?!data|http|\/\/)(\.\.?\/|\/))(.*?)(?:[\'"\s]?\))/g

Comments

0

So here's a cleaned up version that only focuses on images & converts found images relative paths to absolute. This way you can preload easily. This code creates an array with original URL and absolute URL. You can simply loop through the result and preload the absolute URL images

var myString = " \
    background: url(../images/magnifier-ico.png) no-repeat left center; \
    background: url(../../images/globe-ico.png) no-repeat; \
    background: url(../images/magnifier-ico.png) no-repeat left center; \
";

var myRegexp = /(?:\(['|"]?)(.*?\.(png|jpg|gif|jpeg|tiff){1})(?:['|"]?\))/gi;

// Set location of CSS file being read
var cssFile = "/css/mobile/style.css";

// Figure out depth of the css file in relation to root
var cssPath = cssFile.split("/").filter(function(item){return item.length>0;});
var depth = (cssPath.length);

// Array to store found images
var images = [];

// Start search
var match = myRegexp.exec(myString);
while (match) {
  // get image
  var foundImage = match[1];

  // Look for next one
  match = myRegexp.exec(myString);

  // Convert relative path to absolute
  var relativeDepth = 0;
  var pathRegexp = /\.\.\//gi;
  var pathMatch = pathRegexp.exec(foundImage);
  while(pathMatch){
    relativeDepth++;
    pathMatch = pathRegexp.exec(foundImage);
  }
  // Strip the relativity
  var pathlessImage = foundImage.split("../").join("");
  // Now to the final conversion
  var absolute = "";
  for(var i=0;i<depth-relativeDepth-1;i++)
    // Reconstruct it all back
    absolute += "/" + cssPath[i];

  // Now add image name
  absolute += "/" + pathlessImage;

  // Store final cleaned up product
  images.push({original:foundImage,absolute:absolute});
}

console.log(images);

Here's working JSbin http://jsbin.com/nalimaruvu/2/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.