Skip to content

Commit

Permalink
Add image-set()
Browse files Browse the repository at this point in the history
  • Loading branch information
LeaVerou committed Mar 30, 2017
1 parent 20d0475 commit eca625f
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 59 deletions.
114 changes: 59 additions & 55 deletions prefixfree.js
Expand Up @@ -30,7 +30,7 @@ var self = window.StyleFix = {
parent = link.parentNode,
xhr = new XMLHttpRequest(),
process;

xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
process();
Expand All @@ -39,10 +39,10 @@ var self = window.StyleFix = {

process = function() {
var css = xhr.responseText;

if(css && link.parentNode && (!xhr.status || xhr.status < 400 || xhr.status > 600)) {
css = self.fix(css, true, link);

// Convert relative URLs to absolute, if needed
if(css && base) {
css = css.replace(/url\(\s*?((?:"|')?)(.+?)\1\s*?\)/gi, function($0, quote, url) {
Expand Down Expand Up @@ -70,7 +70,7 @@ var self = window.StyleFix = {
var escaped_base = base.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1");
css = css.replace(RegExp('\\b(behavior:\\s*?url\\(\'?"?)' + escaped_base, 'gi'), '$1');
}

var style = document.createElement('style');
style.textContent = '/*# sourceURL='+link.getAttribute('href')+' */\n/*@ sourceURL='+link.getAttribute('href')+' */\n' + css;
style.media = link.media;
Expand All @@ -81,7 +81,7 @@ var self = window.StyleFix = {

parent.insertBefore(style, link);
parent.removeChild(link);

style.media = link.media; // Duplicate is intentional. See issue #31
}
};
Expand All @@ -99,7 +99,7 @@ var self = window.StyleFix = {
xhr.send(null);
}
}

link.setAttribute('data-inprogress', '');
},

Expand All @@ -108,50 +108,50 @@ var self = window.StyleFix = {
return;
}
var disabled = style.disabled;

style.textContent = self.fix(style.textContent, true, style);

style.disabled = disabled;
},

styleAttribute: function(element) {
var css = element.getAttribute('style');

css = self.fix(css, false, element);

element.setAttribute('style', css);
},

process: function() {
// Linked stylesheets
$('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);

// Inline stylesheets
$('style').forEach(StyleFix.styleElement);

// Inline styles
$('[style]').forEach(StyleFix.styleAttribute);
},

register: function(fixer, index) {
(self.fixers = self.fixers || [])
.splice(index === undefined? self.fixers.length : index, 0, fixer);
},

fix: function(css, raw, element) {
if(self.fixers) {
for(var i=0; i<self.fixers.length; i++) {
css = self.fixers[i](css, raw, element) || css;
}
}

return css;
},

camelCase: function(str) {
return str.replace(/-([a-z])/g, function($0, $1) { return $1.toUpperCase(); }).replace('-','');
},

deCamelCase: function(str) {
return str.replace(/[A-Z]/g, function($0) { return '-' + $0.toLowerCase() });
}
Expand All @@ -164,7 +164,7 @@ var self = window.StyleFix = {
setTimeout(function(){
$('link[rel="stylesheet"]').forEach(StyleFix.link);
}, 10);

document.addEventListener('DOMContentLoaded', StyleFix.process, false);
})();

Expand All @@ -186,59 +186,59 @@ if(!window.StyleFix || !window.getComputedStyle) {
// Private helper
function fix(what, before, after, replacement, css) {
what = self[what];

if(what.length) {
var regex = RegExp(before + '(' + what.join('|') + ')' + after, 'gi');

css = css.replace(regex, replacement);
}

return css;
}

var self = window.PrefixFree = {
prefixCSS: function(css, raw, element) {
var prefix = self.prefix;

// Gradient angles hotfix
if(self.functions.indexOf('linear-gradient') > -1) {
// Gradients are supported with a prefix, convert angles to legacy
css = css.replace(/(\s|:|,)(repeating-)?linear-gradient\(\s*(-?\d*\.?\d*)deg/ig, function ($0, delim, repeating, deg) {
return delim + (repeating || '') + 'linear-gradient(' + (90-deg) + 'deg';
});
}

css = fix('functions', '(\\s|:|,)', '\\s*\\(', '$1' + prefix + '$2(', css);
css = fix('keywords', '(\\s|:)', '(\\s|;|\\}|$)', '$1' + prefix + '$2$3', css);
css = fix('properties', '(^|\\{|\\s|;)', '\\s*:', '$1' + prefix + '$2:', css);

// Prefix properties *inside* values (issue #8)
if (self.properties.length) {
var regex = RegExp('\\b(' + self.properties.join('|') + ')(?!:)', 'gi');

css = fix('valueProperties', '\\b', ':(.+?);', function($0) {
return $0.replace(regex, prefix + "$1")
}, css);
}

if(raw) {
css = fix('selectors', '', '\\b', self.prefixSelector, css);
css = fix('atrules', '@', '\\b', '@' + prefix + '$1', css);
}

// Fix double prefixing
css = css.replace(RegExp('-' + prefix, 'g'), '-');

// Prefix wildcard
css = css.replace(/-\*-(?=[a-z]+)/gi, self.prefix);

return css;
},

property: function(property) {
return (self.properties.indexOf(property) >=0 ? self.prefix : '') + property;
},

value: function(value, property) {
value = fix('functions', '(^|\\s|,)', '\\s*\\(', '$1' + self.prefix + '$2(', value);
value = fix('keywords', '(^|\\s)', '(\\s|$)', '$1' + self.prefix + '$2$3', value);
Expand All @@ -249,15 +249,15 @@ var self = window.PrefixFree = {

return value;
},

prefixSelector: function(selector) {
return self.selectorMap[selector] || selector
},

// Warning: Prefixes no matter what, even if the property is supported prefix-less
prefixProperty: function(property, camelCase) {
var prefixed = self.prefix + property;

return camelCase? StyleFix.camelCase(prefixed) : prefixed;
}
};
Expand All @@ -271,7 +271,7 @@ var self = window.PrefixFree = {
shorthands = {},
style = getComputedStyle(document.documentElement, null),
dummy = document.createElement('div').style;

// Why are we doing this instead of iterating over properties in a .style object? Because Webkit.
// 1. Older Webkit won't iterate over those.
// 2. Recent Webkit will, but the 'Webkit'-prefixed properties are not enumerable. The 'webkit'
Expand All @@ -280,17 +280,17 @@ var self = window.PrefixFree = {
var iterate = function(property) {
if(property.charAt(0) === '-') {
properties.push(property);

var parts = property.split('-'),
prefix = parts[1];

// Count prefix uses
prefixes[prefix] = ++prefixes[prefix] || 1;

// This helps determining shorthands
while(parts.length > 3) {
parts.pop();

var shorthand = parts.join('-');

if(supported(shorthand) && properties.indexOf(shorthand) === -1) {
Expand All @@ -302,7 +302,7 @@ var self = window.PrefixFree = {
supported = function(property) {
return StyleFix.camelCase(property) in dummy;
}

// Some browsers have numerical indices for the properties, some don't
if(style && style.length > 0) {
for(var i=0; i<style.length; i++) {
Expand All @@ -324,33 +324,33 @@ var self = window.PrefixFree = {
highest = {prefix: prefix, uses: uses};
}
}

self.prefix = '-' + highest.prefix + '-';
self.Prefix = StyleFix.camelCase(self.prefix);

self.properties = [];

// Get properties ONLY supported with a prefix
for(var i=0; i<properties.length; i++) {
var property = properties[i];

if(property.indexOf(self.prefix) === 0) { // we might have multiple prefixes, like Opera
var unprefixed = property.slice(self.prefix.length);

if(!supported(unprefixed)) {
self.properties.push(unprefixed);
}
}
}

// IE fix
if(self.Prefix == 'Ms'
&& !('transform' in dummy)
&& !('MsTransform' in dummy)
if(self.Prefix == 'Ms'
&& !('transform' in dummy)
&& !('MsTransform' in dummy)
&& ('msTransform' in dummy)) {
self.properties.push('transform', 'transform-origin');
self.properties.push('transform', 'transform-origin');
}

self.properties.sort();
})();

Expand All @@ -375,6 +375,10 @@ var functions = {
'cross-fade': {
property: 'backgroundImage',
params: 'url(a.png), url(b.png), 50%'
},
'image-set': {
property: 'backgroundImage',
params: 'url(a.png) 1x, url(b.png) 2x'
}
};

Expand All @@ -384,7 +388,7 @@ functions['repeating-radial-gradient'] =
functions['radial-gradient'] =
functions['linear-gradient'];

// Note: The properties assigned are just to *test* support.
// Note: The properties assigned are just to *test* support.
// The keywords will be prefixed everywhere.
var keywords = {
'initial': 'color',
Expand Down Expand Up @@ -422,7 +426,7 @@ for (var func in functions) {
var test = functions[func],
property = test.property,
value = func + '(' + test.params + ')';

if (!supported(value, property)
&& supported(self.prefix + value, property)) {
// It's supported, but with a prefix
Expand All @@ -447,7 +451,7 @@ for (var keyword in keywords) {
**************************************/
(function() {

var
var
selectors = {
':any-link': null,
'::backdrop': null,
Expand Down Expand Up @@ -477,7 +481,7 @@ var style = root.appendChild(document.createElement('style'));

function supported(selector) {
style.textContent = selector + '{}'; // Safari 4 has issues with style.innerHTML

return !!style.sheet.cssRules.length;
}

Expand All @@ -492,7 +496,7 @@ for(var selector in selectors) {

for(var atrule in atrules) {
var test = atrule + ' ' + (atrules[atrule] || '');

if(!supported('@' + test) && supported('@' + self.prefix + test)) {
self.atrules.push(atrule);
}
Expand Down
9 changes: 5 additions & 4 deletions prefixfree.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit eca625f

Please sign in to comment.