mirror of
https://github.com/twbs/bootstrap.git
synced 2024-12-01 13:24:25 +01:00
Merge pull request #8187 from imsky/3.0.0-wip
upgrade holder to 2.0, update thumbnail examples in docs to fit inside containers
This commit is contained in:
commit
1555992e35
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Holder - 1.9 - client side image placeholders
|
Holder - 2.0 - client side image placeholders
|
||||||
(c) 2012-2013 Ivan Malopinsky / http://imsky.co
|
(c) 2012-2013 Ivan Malopinsky / http://imsky.co
|
||||||
|
|
||||||
Provided under the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0
|
Provided under the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0
|
||||||
@ -41,19 +41,22 @@ if (!Object.prototype.hasOwnProperty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
function text_size(width, height, template) {
|
function text_size(width, height, template) {
|
||||||
var dimension_arr = [height, width].sort();
|
height = parseInt(height,10);
|
||||||
var maxFactor = Math.round(dimension_arr[1] / 16),
|
width = parseInt(width,10);
|
||||||
minFactor = Math.round(dimension_arr[0] / 16);
|
var bigSide = Math.max(height, width)
|
||||||
var text_height = Math.max(template.size, maxFactor);
|
var smallSide = Math.min(height, width)
|
||||||
|
var scale = 1 / 12;
|
||||||
|
var newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale);
|
||||||
return {
|
return {
|
||||||
height: text_height
|
height: Math.round(Math.max(template.size, newHeight))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function draw(ctx, dimensions, template, ratio) {
|
function draw(ctx, dimensions, template, ratio) {
|
||||||
var ts = text_size(dimensions.width, dimensions.height, template);
|
var ts = text_size(dimensions.width, dimensions.height, template);
|
||||||
var text_height = ts.height;
|
var text_height = ts.height;
|
||||||
var width = dimensions.width * ratio, height = dimensions.height * ratio;
|
var width = dimensions.width * ratio,
|
||||||
|
height = dimensions.height * ratio;
|
||||||
var font = template.font ? template.font : "sans-serif";
|
var font = template.font ? template.font : "sans-serif";
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
@ -62,13 +65,14 @@ function draw(ctx, dimensions, template, ratio) {
|
|||||||
ctx.fillStyle = template.background;
|
ctx.fillStyle = template.background;
|
||||||
ctx.fillRect(0, 0, width, height);
|
ctx.fillRect(0, 0, width, height);
|
||||||
ctx.fillStyle = template.foreground;
|
ctx.fillStyle = template.foreground;
|
||||||
ctx.font = "bold " + text_height + "px "+font;
|
ctx.font = "bold " + text_height + "px " + font;
|
||||||
var text = template.text ? template.text : (dimensions.width + "x" + dimensions.height);
|
var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
|
||||||
if (ctx.measureText(text).width / width > 1) {
|
var text_width = ctx.measureText(text).width;
|
||||||
text_height = template.size / (ctx.measureText(text).width / width);
|
if (text_width / width >= 0.75) {
|
||||||
|
text_height = Math.floor(text_height * 0.75 * (width/text_width));
|
||||||
}
|
}
|
||||||
//Resetting font size if necessary
|
//Resetting font size if necessary
|
||||||
ctx.font = "bold " + (text_height * ratio) + "px "+font;
|
ctx.font = "bold " + (text_height * ratio) + "px " + font;
|
||||||
ctx.fillText(text, (width / 2), (height / 2), width);
|
ctx.fillText(text, (width / 2), (height / 2), width);
|
||||||
return canvas.toDataURL("image/png");
|
return canvas.toDataURL("image/png");
|
||||||
}
|
}
|
||||||
@ -78,89 +82,71 @@ function render(mode, el, holder, src) {
|
|||||||
theme = holder.theme,
|
theme = holder.theme,
|
||||||
text = holder.text ? decodeURIComponent(holder.text) : holder.text;
|
text = holder.text ? decodeURIComponent(holder.text) : holder.text;
|
||||||
var dimensions_caption = dimensions.width + "x" + dimensions.height;
|
var dimensions_caption = dimensions.width + "x" + dimensions.height;
|
||||||
theme = (text ? extend(theme, { text: text }) : theme);
|
theme = (text ? extend(theme, {
|
||||||
theme = (holder.font ? extend(theme, {font: holder.font}) : theme);
|
text: text
|
||||||
|
}) : theme);
|
||||||
var ratio = 1;
|
theme = (holder.font ? extend(theme, {
|
||||||
if(window.devicePixelRatio && window.devicePixelRatio > 1){
|
font: holder.font
|
||||||
ratio = window.devicePixelRatio;
|
}) : theme);
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == "image") {
|
if (mode == "image") {
|
||||||
el.setAttribute("data-src", src);
|
el.setAttribute("data-src", src);
|
||||||
el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
|
el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
|
||||||
|
if (fallback || !holder.auto) {
|
||||||
if(fallback || !holder.auto){
|
|
||||||
el.style.width = dimensions.width + "px";
|
el.style.width = dimensions.width + "px";
|
||||||
el.style.height = dimensions.height + "px";
|
el.style.height = dimensions.height + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fallback) {
|
if (fallback) {
|
||||||
el.style.backgroundColor = theme.background;
|
el.style.backgroundColor = theme.background;
|
||||||
|
} else {
|
||||||
}
|
|
||||||
else{
|
|
||||||
el.setAttribute("src", draw(ctx, dimensions, theme, ratio));
|
el.setAttribute("src", draw(ctx, dimensions, theme, ratio));
|
||||||
}
|
}
|
||||||
} else {
|
} else if (mode == "background") {
|
||||||
if (!fallback) {
|
if (!fallback) {
|
||||||
el.style.backgroundImage = "url(" + draw(ctx, dimensions, theme, ratio) + ")";
|
el.style.backgroundImage = "url(" + draw(ctx, dimensions, theme, ratio) + ")";
|
||||||
el.style.backgroundSize = dimensions.width+"px "+dimensions.height+"px";
|
el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px";
|
||||||
|
}
|
||||||
|
} else if (mode == "fluid") {
|
||||||
|
el.setAttribute("data-src", src);
|
||||||
|
el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
|
||||||
|
if (dimensions.height.substr(-1) == "%") {
|
||||||
|
el.style.height = dimensions.height
|
||||||
|
} else {
|
||||||
|
el.style.height = dimensions.height + "px"
|
||||||
|
}
|
||||||
|
if (dimensions.width.substr(-1) == "%") {
|
||||||
|
el.style.width = dimensions.width
|
||||||
|
} else {
|
||||||
|
el.style.width = dimensions.width + "px"
|
||||||
|
}
|
||||||
|
if (el.style.display == "inline" || el.style.display == "") {
|
||||||
|
el.style.display = "block";
|
||||||
|
}
|
||||||
|
if (fallback) {
|
||||||
|
el.style.backgroundColor = theme.background;
|
||||||
|
} else {
|
||||||
|
el.holderData = holder;
|
||||||
|
fluid_images.push(el);
|
||||||
|
fluid_update(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function fluid(el, holder, src) {
|
function fluid_update(element) {
|
||||||
var dimensions = holder.dimensions,
|
var images;
|
||||||
theme = holder.theme,
|
if (element.nodeType == null) {
|
||||||
text = holder.text;
|
images = fluid_images;
|
||||||
var dimensions_caption = dimensions.width + "x" + dimensions.height;
|
|
||||||
theme = (text ? extend(theme, {
|
|
||||||
text: text
|
|
||||||
}) : theme);
|
|
||||||
|
|
||||||
var fluid = document.createElement("div");
|
|
||||||
|
|
||||||
fluid.style.backgroundColor = theme.background;
|
|
||||||
fluid.style.color = theme.foreground;
|
|
||||||
fluid.className = el.className + " holderjs-fluid";
|
|
||||||
fluid.style.width = holder.dimensions.width + (holder.dimensions.width.indexOf("%")>0?"":"px");
|
|
||||||
fluid.style.height = holder.dimensions.height + (holder.dimensions.height.indexOf("%")>0?"":"px");
|
|
||||||
fluid.id = el.id;
|
|
||||||
|
|
||||||
el.style.width=0;
|
|
||||||
el.style.height=0;
|
|
||||||
|
|
||||||
if (theme.text) {
|
|
||||||
fluid.appendChild(document.createTextNode(theme.text))
|
|
||||||
} else {
|
} else {
|
||||||
fluid.appendChild(document.createTextNode(dimensions_caption))
|
images = [element]
|
||||||
fluid_images.push(fluid);
|
|
||||||
setTimeout(fluid_update, 0);
|
|
||||||
}
|
}
|
||||||
|
for (i in images) {
|
||||||
el.parentNode.insertBefore(fluid, el.nextSibling)
|
var el = images[i]
|
||||||
|
if (el.holderData) {
|
||||||
if(window.jQuery){
|
var holder = el.holderData;
|
||||||
jQuery(function($){
|
el.setAttribute("src", draw(ctx, {
|
||||||
$(el).on("load", function(){
|
height: el.clientHeight,
|
||||||
el.style.width = fluid.style.width;
|
width: el.clientWidth
|
||||||
el.style.height = fluid.style.height;
|
}, holder.theme, ratio));
|
||||||
$(el).show();
|
|
||||||
$(fluid).remove();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function fluid_update() {
|
|
||||||
for (i in fluid_images) {
|
|
||||||
if(!fluid_images.hasOwnProperty(i)) continue;
|
|
||||||
var el = fluid_images[i],
|
|
||||||
label = el.firstChild;
|
|
||||||
|
|
||||||
el.style.lineHeight = el.offsetHeight+"px";
|
|
||||||
label.data = el.offsetWidth + "x" + el.offsetHeight;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,10 +172,9 @@ function parse_flags(flags, options) {
|
|||||||
ret.theme = options.themes[flag];
|
ret.theme = options.themes[flag];
|
||||||
} else if (app.flags.text.match(flag)) {
|
} else if (app.flags.text.match(flag)) {
|
||||||
ret.text = app.flags.text.output(flag);
|
ret.text = app.flags.text.output(flag);
|
||||||
} else if(app.flags.font.match(flag)){
|
} else if (app.flags.font.match(flag)) {
|
||||||
ret.font = app.flags.font.output(flag);
|
ret.font = app.flags.font.output(flag);
|
||||||
}
|
} else if (app.flags.auto.match(flag)) {
|
||||||
else if(app.flags.auto.match(flag)){
|
|
||||||
ret.auto = true;
|
ret.auto = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,6 +183,8 @@ function parse_flags(flags, options) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!canvas.getContext) {
|
if (!canvas.getContext) {
|
||||||
fallback = true;
|
fallback = true;
|
||||||
} else {
|
} else {
|
||||||
@ -210,6 +197,15 @@ if (!canvas.getContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dpr = 1, bsr = 1;
|
||||||
|
|
||||||
|
if(!fallback){
|
||||||
|
dpr = window.devicePixelRatio || 1,
|
||||||
|
bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ratio = dpr / bsr;
|
||||||
|
|
||||||
var fluid_images = [];
|
var fluid_images = [];
|
||||||
|
|
||||||
var settings = {
|
var settings = {
|
||||||
@ -277,7 +273,7 @@ app.flags = {
|
|||||||
},
|
},
|
||||||
font: {
|
font: {
|
||||||
regex: /font\:(.*)/,
|
regex: /font\:(.*)/,
|
||||||
output: function(val){
|
output: function (val) {
|
||||||
return this.regex.exec(val)[1];
|
return this.regex.exec(val)[1];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -287,7 +283,7 @@ app.flags = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (var flag in app.flags) {
|
for (var flag in app.flags) {
|
||||||
if(!app.flags.hasOwnProperty(flag)) continue;
|
if (!app.flags.hasOwnProperty(flag)) continue;
|
||||||
app.flags[flag].match = function (val) {
|
app.flags[flag].match = function (val) {
|
||||||
return val.match(this.regex)
|
return val.match(this.regex)
|
||||||
}
|
}
|
||||||
@ -311,26 +307,24 @@ app.add_image = function (src, el) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
app.run = function (o) {
|
app.run = function (o) {
|
||||||
var options = extend(settings, o), images = [];
|
var options = extend(settings, o),
|
||||||
|
images = [], imageNodes = [], bgnodes = [];
|
||||||
|
|
||||||
if(options.images instanceof window.NodeList){
|
if(typeof(options.images) == "string"){
|
||||||
imageNodes = options.images;
|
|
||||||
}
|
|
||||||
else if(options.images instanceof window.Node){
|
|
||||||
imageNodes = [options.images];
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
imageNodes = selector(options.images);
|
imageNodes = selector(options.images);
|
||||||
}
|
}
|
||||||
|
else if (window.NodeList && options.images instanceof window.NodeList) {
|
||||||
|
imageNodes = options.images;
|
||||||
|
} else if (window.Node && options.images instanceof window.Node) {
|
||||||
|
imageNodes = [options.images];
|
||||||
|
}
|
||||||
|
|
||||||
if(options.elements instanceof window.NodeList){
|
if(typeof(options.bgnodes) == "string"){
|
||||||
bgnodes = options.bgnodes;
|
|
||||||
}
|
|
||||||
else if(options.bgnodes instanceof window.Node){
|
|
||||||
bgnodes = [options.bgnodes];
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
bgnodes = selector(options.bgnodes);
|
bgnodes = selector(options.bgnodes);
|
||||||
|
} else if (window.NodeList && options.elements instanceof window.NodeList) {
|
||||||
|
bgnodes = options.bgnodes;
|
||||||
|
} else if (window.Node && options.bgnodes instanceof window.Node) {
|
||||||
|
bgnodes = [options.bgnodes];
|
||||||
}
|
}
|
||||||
|
|
||||||
preempted = true;
|
preempted = true;
|
||||||
@ -338,19 +332,19 @@ app.run = function (o) {
|
|||||||
for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]);
|
for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]);
|
||||||
|
|
||||||
var holdercss = document.getElementById("holderjs-style");
|
var holdercss = document.getElementById("holderjs-style");
|
||||||
|
if (!holdercss) {
|
||||||
if(!holdercss){
|
|
||||||
holdercss = document.createElement("style");
|
holdercss = document.createElement("style");
|
||||||
holdercss.setAttribute("id", "holderjs-style");
|
holdercss.setAttribute("id", "holderjs-style");
|
||||||
holdercss.type = "text/css";
|
holdercss.type = "text/css";
|
||||||
document.getElementsByTagName("head")[0].appendChild(holdercss);
|
document.getElementsByTagName("head")[0].appendChild(holdercss);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(holdercss.styleSheet){
|
if (!options.nocss) {
|
||||||
holdercss.styleSheet += options.stylesheet;
|
if (holdercss.styleSheet) {
|
||||||
|
holdercss.styleSheet.cssText += options.stylesheet;
|
||||||
|
} else {
|
||||||
|
holdercss.appendChild(document.createTextNode(options.stylesheet));
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
holdercss.textContent+= options.stylesheet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)");
|
var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)");
|
||||||
@ -359,22 +353,44 @@ app.run = function (o) {
|
|||||||
var src = window.getComputedStyle(bgnodes[i], null)
|
var src = window.getComputedStyle(bgnodes[i], null)
|
||||||
.getPropertyValue("background-image");
|
.getPropertyValue("background-image");
|
||||||
var flags = src.match(cssregex);
|
var flags = src.match(cssregex);
|
||||||
|
var bgsrc = bgnodes[i].getAttribute("data-background-src");
|
||||||
|
|
||||||
if (flags) {
|
if (flags) {
|
||||||
var holder = parse_flags(flags[1].split("/"), options);
|
var holder = parse_flags(flags[1].split("/"), options);
|
||||||
if (holder) {
|
if (holder) {
|
||||||
render("background", bgnodes[i], holder, src);
|
render("background", bgnodes[i], holder, src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(bgsrc != null){
|
||||||
|
var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1)
|
||||||
|
.split("/"), options);
|
||||||
|
if(holder){
|
||||||
|
render("background", bgnodes[i], holder, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var l = images.length, i = 0; i < l; i++) {
|
for (l = images.length, i = 0; i < l; i++) {
|
||||||
var src = images[i].getAttribute("src") || images[i].getAttribute("data-src");
|
|
||||||
if (src != null && src.indexOf(options.domain) >= 0) {
|
var attr_src = attr_data_src = src = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
attr_src = images[i].getAttribute("src");
|
||||||
|
attr_datasrc = images[i].getAttribute("data-src");
|
||||||
|
}catch(e){}
|
||||||
|
|
||||||
|
if (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) {
|
||||||
|
src = attr_src;
|
||||||
|
} else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) {
|
||||||
|
src = attr_datasrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src) {
|
||||||
var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1)
|
var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1)
|
||||||
.split("/"), options);
|
.split("/"), options);
|
||||||
if (holder) {
|
if (holder) {
|
||||||
if (holder.fluid) {
|
if (holder.fluid) {
|
||||||
fluid(images[i], holder, src);
|
render("fluid", images[i], holder, src)
|
||||||
} else {
|
} else {
|
||||||
render("image", images[i], holder, src);
|
render("image", images[i], holder, src);
|
||||||
}
|
}
|
||||||
@ -394,8 +410,10 @@ contentLoaded(win, function () {
|
|||||||
preempted || app.run();
|
preempted || app.run();
|
||||||
});
|
});
|
||||||
|
|
||||||
if ( typeof define === "function" && define.amd ) {
|
if (typeof define === "function" && define.amd) {
|
||||||
define( "Holder", [], function () { return app; } );
|
define("Holder", [], function () {
|
||||||
|
return app;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
})(Holder, window);
|
})(Holder, window);
|
||||||
|
@ -1759,22 +1759,22 @@ body { padding-bottom: 70px; }
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<a href="#" class="thumbnail">
|
<a href="#" class="thumbnail">
|
||||||
<img data-src="holder.js/260x180" alt="">
|
<img data-src="holder.js/100%x180" alt="">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<a href="#" class="thumbnail">
|
<a href="#" class="thumbnail">
|
||||||
<img data-src="holder.js/260x180" alt="">
|
<img data-src="holder.js/100%x180" alt="">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<a href="#" class="thumbnail">
|
<a href="#" class="thumbnail">
|
||||||
<img data-src="holder.js/260x180" alt="">
|
<img data-src="holder.js/100%x180" alt="">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<a href="#" class="thumbnail">
|
<a href="#" class="thumbnail">
|
||||||
<img data-src="holder.js/260x180" alt="">
|
<img data-src="holder.js/100%x180" alt="">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1783,7 +1783,7 @@ body { padding-bottom: 70px; }
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<a href="#" class="thumbnail">
|
<a href="#" class="thumbnail">
|
||||||
<img data-src="holder.js/260x180" alt="">
|
<img data-src="holder.js/100%x180" alt="">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
...
|
...
|
||||||
|
Loading…
Reference in New Issue
Block a user