ff-streaming-platform

git clone git://archive.git.mtrnord.blog/MTRNord/ff-streaming-platform.git
Log | Files | Refs | README | LICENSE

holder.js (20260B)


      1 /*!
      2 
      3 Holder - 2.3.2 - client side image placeholders
      4 (c) 2012-2014 Ivan Malopinsky / http://imsky.co
      5 
      6 Provided under the MIT License.
      7 Commercial use requires attribution.
      8 
      9 */
     10 var Holder = Holder || {};
     11 (function (app, win) {
     12 var system_config = {
     13 	use_svg: false,
     14 	use_canvas: false,
     15 	use_fallback: false
     16 };
     17 var instance_config = {};
     18 var preempted = false;
     19 canvas = document.createElement('canvas');
     20 var dpr = 1, bsr = 1;
     21 var resizable_images = [];
     22 
     23 if (!canvas.getContext) {
     24 	system_config.use_fallback = true;
     25 } else {
     26 	if (canvas.toDataURL("image/png")
     27 		.indexOf("data:image/png") < 0) {
     28 		//Android doesn't support data URI
     29 		system_config.use_fallback = true;
     30 	} else {
     31 		var ctx = canvas.getContext("2d");
     32 	}
     33 }
     34 
     35 if(!!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect){
     36 	system_config.use_svg = true;
     37 	system_config.use_canvas = false;
     38 }
     39 
     40 if(!system_config.use_fallback){
     41     dpr = window.devicePixelRatio || 1,
     42     bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
     43 }
     44 
     45 var ratio = dpr / bsr;
     46 
     47 var settings = {
     48 	domain: "holder.js",
     49 	images: "img",
     50 	bgnodes: ".holderjs",
     51 	themes: {
     52 		"gray": {
     53 			background: "#eee",
     54 			foreground: "#aaa",
     55 			size: 12
     56 		},
     57 		"social": {
     58 			background: "#3a5a97",
     59 			foreground: "#fff",
     60 			size: 12
     61 		},
     62 		"industrial": {
     63 			background: "#434A52",
     64 			foreground: "#C2F200",
     65 			size: 12
     66 		},
     67 		"sky": {
     68 			background: "#0D8FDB",
     69 			foreground: "#fff",
     70 			size: 12
     71 		},
     72 		"vine": {
     73 			background: "#39DBAC",
     74 			foreground: "#1E292C",
     75 			size: 12
     76 		},
     77 		"lava": {
     78 			background: "#F8591A",
     79 			foreground: "#1C2846",
     80 			size: 12
     81 		}
     82 	},
     83 	stylesheet: ""
     84 };
     85 app.flags = {
     86 	dimensions: {
     87 		regex: /^(\d+)x(\d+)$/,
     88 		output: function (val) {
     89 			var exec = this.regex.exec(val);
     90 			return {
     91 				width: +exec[1],
     92 				height: +exec[2]
     93 			}
     94 		}
     95 	},
     96 	fluid: {
     97 		regex: /^([0-9%]+)x([0-9%]+)$/,
     98 		output: function (val) {
     99 			var exec = this.regex.exec(val);
    100 			return {
    101 				width: exec[1],
    102 				height: exec[2]
    103 			}
    104 		}
    105 	},
    106 	colors: {
    107 		regex: /#([0-9a-f]{3,})\:#([0-9a-f]{3,})/i,
    108 		output: function (val) {
    109 			var exec = this.regex.exec(val);
    110 			return {
    111 				size: settings.themes.gray.size,
    112 				foreground: "#" + exec[2],
    113 				background: "#" + exec[1]
    114 			}
    115 		}
    116 	},
    117 	text: {
    118 		regex: /text\:(.*)/,
    119 		output: function (val) {
    120 			return this.regex.exec(val)[1];
    121 		}
    122 	},
    123 	font: {
    124 		regex: /font\:(.*)/,
    125 		output: function (val) {
    126 			return this.regex.exec(val)[1];
    127 		}
    128 	},
    129 	auto: {
    130 		regex: /^auto$/
    131 	},
    132 	textmode: {
    133 		regex: /textmode\:(.*)/,
    134 		output: function(val){
    135 			return this.regex.exec(val)[1];
    136 		}
    137 	}
    138 }
    139 
    140 function text_size(width, height, template) {
    141 	height = parseInt(height, 10);
    142 	width = parseInt(width, 10);
    143 	var bigSide = Math.max(height, width)
    144 	var smallSide = Math.min(height, width)
    145 	var scale = 1 / 12;
    146 	var newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale);
    147 	return {
    148 		height: Math.round(Math.max(template.size, newHeight))
    149 	}
    150 }
    151 
    152 var svg_el = (function(){
    153 	//Prevent IE <9 from initializing SVG renderer
    154 	if(!window.XMLSerializer) return;
    155 	var serializer = new XMLSerializer();
    156 	var svg_ns = "http://www.w3.org/2000/svg"
    157 	var svg = document.createElementNS(svg_ns, "svg");
    158 	//IE throws an exception if this is set and Chrome requires it to be set
    159 	if(svg.webkitMatchesSelector){
    160 		svg.setAttribute("xmlns", "http://www.w3.org/2000/svg")
    161 	}
    162 	var bg_el = document.createElementNS(svg_ns, "rect")
    163 	var text_el = document.createElementNS(svg_ns, "text")
    164 	var textnode_el = document.createTextNode(null)
    165 	text_el.setAttribute("text-anchor", "middle")
    166 	text_el.appendChild(textnode_el)
    167 	svg.appendChild(bg_el)
    168 	svg.appendChild(text_el)
    169 
    170 	return function(props){
    171 		svg.setAttribute("width",props.width);
    172 		svg.setAttribute("height", props.height);
    173 		bg_el.setAttribute("width", props.width);
    174 		bg_el.setAttribute("height", props.height);
    175 		bg_el.setAttribute("fill", props.template.background);
    176 		text_el.setAttribute("x", props.width/2)
    177 		text_el.setAttribute("y", props.height/2)
    178 		textnode_el.nodeValue=props.text
    179 		text_el.setAttribute("style", css_properties({
    180 		"fill": props.template.foreground,
    181 		"font-weight": "bold",
    182 		"font-size": props.text_height+"px",
    183 		"font-family":props.font,
    184 		"dominant-baseline":"central"
    185 		}))
    186 		return serializer.serializeToString(svg)
    187 	}
    188 })()
    189 
    190 function css_properties(props){
    191 	var ret = [];
    192 	for(p in props){
    193 		if(props.hasOwnProperty(p)){
    194 			ret.push(p+":"+props[p])
    195 		}
    196 	}
    197 	return ret.join(";")
    198 }
    199 
    200 function draw_canvas(args) {
    201 	var ctx = args.ctx,
    202 		dimensions = args.dimensions,
    203 		template = args.template,
    204 		ratio = args.ratio,
    205 		holder = args.holder,
    206 		literal = holder.textmode == "literal",
    207 		exact = holder.textmode == "exact";
    208 
    209 	var ts = text_size(dimensions.width, dimensions.height, template);
    210 	var text_height = ts.height;
    211 	var width = dimensions.width * ratio,
    212 		height = dimensions.height * ratio;
    213 	var font = template.font ? template.font : "Arial,Helvetica,sans-serif";
    214 	canvas.width = width;
    215 	canvas.height = height;
    216 	ctx.textAlign = "center";
    217 	ctx.textBaseline = "middle";
    218 	ctx.fillStyle = template.background;
    219 	ctx.fillRect(0, 0, width, height);
    220 	ctx.fillStyle = template.foreground;
    221 	ctx.font = "bold " + text_height + "px " + font;
    222 	var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
    223 	if (literal) {
    224 		var dimensions = holder.dimensions;
    225 		text = dimensions.width + "x" + dimensions.height;
    226 	}
    227 	else if(exact && holder.exact_dimensions){
    228 		var dimensions = holder.exact_dimensions;
    229 		text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
    230 	}
    231 	var text_width = ctx.measureText(text).width;
    232 	if (text_width / width >= 0.75) {
    233 		text_height = Math.floor(text_height * 0.75 * (width / text_width));
    234 	}
    235 	//Resetting font size if necessary
    236 	ctx.font = "bold " + (text_height * ratio) + "px " + font;
    237 	ctx.fillText(text, (width / 2), (height / 2), width);
    238 	return canvas.toDataURL("image/png");
    239 }
    240 
    241 function draw_svg(args){
    242 	var dimensions = args.dimensions,
    243 		template = args.template,
    244 		holder = args.holder,
    245 		literal = holder.textmode == "literal",
    246 		exact = holder.textmode == "exact";
    247 
    248 	var ts = text_size(dimensions.width, dimensions.height, template);
    249 	var text_height = ts.height;
    250 	var width = dimensions.width,
    251 		height = dimensions.height;
    252 		
    253 	var font = template.font ? template.font : "Arial,Helvetica,sans-serif";
    254 	var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
    255 	
    256 	if (literal) {
    257 		var dimensions = holder.dimensions;
    258 		text = dimensions.width + "x" + dimensions.height;
    259 	}
    260 	else if(exact && holder.exact_dimensions){
    261 		var dimensions = holder.exact_dimensions;
    262 		text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
    263 	}
    264 	var string = svg_el({
    265 		text: text, 
    266 		width:width, 
    267 		height:height, 
    268 		text_height:text_height, 
    269 		font:font, 
    270 		template:template
    271 	})
    272 	return "data:image/svg+xml;base64,"+btoa(unescape(encodeURIComponent(string)));
    273 }
    274 
    275 function draw(args) {
    276 	if(instance_config.use_canvas && !instance_config.use_svg){
    277 		return draw_canvas(args);
    278 	}
    279 	else{
    280 		return draw_svg(args);
    281 	}
    282 }
    283 
    284 function render(mode, el, holder, src) {
    285 	var dimensions = holder.dimensions,
    286 		theme = holder.theme,
    287 		text = holder.text ? decodeURIComponent(holder.text) : holder.text;
    288 	var dimensions_caption = dimensions.width + "x" + dimensions.height;
    289 	theme = (text ? extend(theme, {
    290 		text: text
    291 	}) : theme);
    292 	theme = (holder.font ? extend(theme, {
    293 		font: holder.font
    294 	}) : theme);
    295 	el.setAttribute("data-src", src);
    296 	holder.theme = theme;
    297 	el.holder_data = holder;
    298 	
    299 	if (mode == "image") {
    300 		el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
    301 		if (instance_config.use_fallback || !holder.auto) {
    302 			el.style.width = dimensions.width + "px";
    303 			el.style.height = dimensions.height + "px";
    304 		}
    305 		if (instance_config.use_fallback) {
    306 			el.style.backgroundColor = theme.background;
    307 		} else {
    308 			el.setAttribute("src", draw({ctx: ctx, dimensions: dimensions, template: theme, ratio:ratio, holder: holder}));
    309 			
    310 			if(holder.textmode && holder.textmode == "exact"){
    311 				resizable_images.push(el);
    312 				resizable_update(el);
    313 			}
    314 			
    315 		}
    316 	} else if (mode == "background") {
    317 		if (!instance_config.use_fallback) {
    318 			el.style.backgroundImage = "url(" + draw({ctx:ctx, dimensions: dimensions, template: theme, ratio: ratio, holder: holder}) + ")";
    319 			el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px";
    320 		}
    321 	} else if (mode == "fluid") {
    322 		el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
    323 		if (dimensions.height.slice(-1) == "%") {
    324 			el.style.height = dimensions.height
    325 		} else if(holder.auto == null || !holder.auto){
    326 			el.style.height = dimensions.height + "px"
    327 		}
    328 		if (dimensions.width.slice(-1) == "%") {
    329 			el.style.width = dimensions.width
    330 		} else if(holder.auto == null || !holder.auto){
    331 			el.style.width = dimensions.width + "px"
    332 		}
    333 		if (el.style.display == "inline" || el.style.display === "" || el.style.display == "none") {
    334 			el.style.display = "block";
    335 		}
    336 		
    337 		set_initial_dimensions(el)
    338 		
    339 		if (instance_config.use_fallback) {
    340 			el.style.backgroundColor = theme.background;
    341 		} else {
    342 			resizable_images.push(el);
    343 			resizable_update(el);
    344 		}
    345 	}
    346 }
    347 
    348 function dimension_check(el, callback) {
    349 	var dimensions = {
    350 		height: el.clientHeight,
    351 		width: el.clientWidth
    352 	};
    353 	if (!dimensions.height && !dimensions.width) {
    354 		el.setAttribute("data-holder-invisible", true)
    355 		callback.call(this, el)
    356 	}
    357 	else{
    358 		el.removeAttribute("data-holder-invisible")
    359 		return dimensions;
    360 	}
    361 }
    362 
    363 function set_initial_dimensions(el){
    364 	if(el.holder_data){
    365 		var dimensions = dimension_check(el, app.invisible_error_fn( set_initial_dimensions))
    366 		if(dimensions){
    367 			var holder = el.holder_data;
    368 			holder.initial_dimensions = dimensions;
    369 			holder.fluid_data = {
    370 				fluid_height: holder.dimensions.height.slice(-1) == "%",
    371 				fluid_width: holder.dimensions.width.slice(-1) == "%",
    372 				mode: null
    373 			}
    374 			if(holder.fluid_data.fluid_width && !holder.fluid_data.fluid_height){
    375 				holder.fluid_data.mode = "width"
    376 				holder.fluid_data.ratio = holder.initial_dimensions.width / parseFloat(holder.dimensions.height)
    377 			}
    378 			else if(!holder.fluid_data.fluid_width && holder.fluid_data.fluid_height){
    379 				holder.fluid_data.mode = "height";
    380 				holder.fluid_data.ratio = parseFloat(holder.dimensions.width) / holder.initial_dimensions.height
    381 			}
    382 		}
    383 	}
    384 }
    385 
    386 function resizable_update(element) {
    387 	var images;
    388 	if (element.nodeType == null) {
    389 		images = resizable_images;
    390 	} else {
    391 		images = [element]
    392 	}
    393 	for (var i in images) {
    394 		if (!images.hasOwnProperty(i)) {
    395 			continue;
    396 		}
    397 		var el = images[i]
    398 		if (el.holder_data) {
    399 			var holder = el.holder_data;
    400 			var dimensions = dimension_check(el, app.invisible_error_fn( resizable_update))
    401 			if(dimensions){
    402 				if(holder.fluid){
    403 					if(holder.auto){
    404 						switch(holder.fluid_data.mode){
    405 							case "width":
    406 								dimensions.height = dimensions.width / holder.fluid_data.ratio;
    407 							break;
    408 							case "height":
    409 								dimensions.width = dimensions.height * holder.fluid_data.ratio;
    410 							break;
    411 						}
    412 					}
    413 					el.setAttribute("src", draw({
    414 						ctx: ctx,
    415 						dimensions: dimensions,
    416 						template: holder.theme,
    417 						ratio: ratio,
    418 						holder: holder
    419 					}))
    420 				}
    421 				if(holder.textmode && holder.textmode == "exact"){
    422 					holder.exact_dimensions = dimensions;
    423 					el.setAttribute("src", draw({
    424 						ctx: ctx,
    425 						dimensions: holder.dimensions,
    426 						template: holder.theme,
    427 						ratio: ratio,
    428 						holder: holder
    429 					}))
    430 				}
    431 			}
    432 		}
    433 	}
    434 }
    435 
    436 function parse_flags(flags, options) {
    437 	var ret = {
    438 		theme: extend(settings.themes.gray, {})
    439 	};
    440 	var render = false;
    441 	for (var fl = flags.length, j = 0; j < fl; j++) {
    442 		var flag = flags[j];
    443 		if (app.flags.dimensions.match(flag)) {
    444 			render = true;
    445 			ret.dimensions = app.flags.dimensions.output(flag);
    446 		} else if (app.flags.fluid.match(flag)) {
    447 			render = true;
    448 			ret.dimensions = app.flags.fluid.output(flag);
    449 			ret.fluid = true;
    450 		} else if (app.flags.textmode.match(flag)) {
    451 			ret.textmode = app.flags.textmode.output(flag)
    452 		} else if (app.flags.colors.match(flag)) {
    453 			ret.theme = app.flags.colors.output(flag);
    454 		} else if (options.themes[flag]) {
    455 			//If a theme is specified, it will override custom colors
    456 			if(options.themes.hasOwnProperty(flag)){
    457 				ret.theme = extend(options.themes[flag], {});
    458 			}
    459 		} else if (app.flags.font.match(flag)) {
    460 			ret.font = app.flags.font.output(flag);
    461 		} else if (app.flags.auto.match(flag)) {
    462 			ret.auto = true;
    463 		} else if (app.flags.text.match(flag)) {
    464 			ret.text = app.flags.text.output(flag);
    465 		}
    466 	}
    467 	return render ? ret : false;
    468 }
    469 
    470 for (var flag in app.flags) {
    471 	if (!app.flags.hasOwnProperty(flag)) continue;
    472 	app.flags[flag].match = function (val) {
    473 		return val.match(this.regex)
    474 	}
    475 }
    476 
    477 app.invisible_error_fn = function(fn){
    478 	return function(el){
    479 		if(el.hasAttribute("data-holder-invisible")){
    480 			throw new Error("Holder: invisible placeholder")
    481 		}
    482 	}
    483 }
    484 
    485 app.add_theme = function (name, theme) {
    486 	name != null && theme != null && (settings.themes[name] = theme);
    487 	return app;
    488 };
    489 
    490 app.add_image = function (src, el) {
    491 	var node = selector(el);
    492 	if (node.length) {
    493 		for (var i = 0, l = node.length; i < l; i++) {
    494 			var img = document.createElement("img")
    495 			img.setAttribute("data-src", src);
    496 			node[i].appendChild(img);
    497 		}
    498 	}
    499 	return app;
    500 };
    501 
    502 app.run = function (o) {
    503 
    504 	instance_config = extend({}, system_config)
    505 	preempted = true;
    506 
    507 	var options = extend(settings, o),
    508 		images = [],
    509 		imageNodes = [],
    510 		bgnodes = [];
    511 
    512 	if(options.use_canvas != null && options.use_canvas){
    513 		instance_config.use_canvas = true;
    514 		instance_config.use_svg = false;
    515 	}
    516 			
    517 	if (typeof (options.images) == "string") {
    518 		imageNodes = selector(options.images);
    519 	} else if (window.NodeList && options.images instanceof window.NodeList) {
    520 		imageNodes = options.images;
    521 	} else if (window.Node && options.images instanceof window.Node) {
    522 		imageNodes = [options.images];
    523 	} else if(window.HTMLCollection && options.images instanceof window.HTMLCollection){
    524 		imageNodes = options.images
    525 	}
    526 
    527 	if (typeof (options.bgnodes) == "string") {
    528 		bgnodes = selector(options.bgnodes);
    529 	} else if (window.NodeList && options.elements instanceof window.NodeList) {
    530 		bgnodes = options.bgnodes;
    531 	} else if (window.Node && options.bgnodes instanceof window.Node) {
    532 		bgnodes = [options.bgnodes];
    533 	}
    534 	for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]);
    535 	
    536 	var holdercss = document.getElementById("holderjs-style");
    537 	if (!holdercss) {
    538 		holdercss = document.createElement("style");
    539 		holdercss.setAttribute("id", "holderjs-style");
    540 		holdercss.type = "text/css";
    541 		document.getElementsByTagName("head")[0].appendChild(holdercss);
    542 	}
    543 	
    544 	if (!options.nocss) {
    545 		if (holdercss.styleSheet) {
    546 			holdercss.styleSheet.cssText += options.stylesheet;
    547 		} else {
    548 			if(options.stylesheet.length){
    549 				holdercss.appendChild(document.createTextNode(options.stylesheet));
    550 			}
    551 		}
    552 	}
    553 	
    554 	var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)");
    555 	for (var l = bgnodes.length, i = 0; i < l; i++) {
    556 		var src = window.getComputedStyle(bgnodes[i], null)
    557 			.getPropertyValue("background-image");
    558 		var flags = src.match(cssregex);
    559 		var bgsrc = bgnodes[i].getAttribute("data-background-src");
    560 		if (flags) {
    561 			var holder = parse_flags(flags[1].split("/"), options);
    562 			if (holder) {
    563 				render("background", bgnodes[i], holder, src);
    564 			}
    565 		} else if (bgsrc != null) {
    566 			var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1)
    567 				.split("/"), options);
    568 			if (holder) {
    569 				render("background", bgnodes[i], holder, src);
    570 			}
    571 		}
    572 	}
    573 	for (l = images.length, i = 0; i < l; i++) {
    574 		var attr_data_src, attr_src;
    575 		attr_src = attr_data_src = src = null;
    576 		try {
    577 			attr_src = images[i].getAttribute("src");
    578 			attr_datasrc = images[i].getAttribute("data-src");
    579 		} catch (e) {}
    580 		if (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) {
    581 			src = attr_src;
    582 		} else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) {
    583 			src = attr_datasrc;
    584 		}
    585 		if (src) {
    586 			var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1).split("/"), options);
    587 			if (holder) {
    588 				if (holder.fluid) {
    589 					render("fluid", images[i], holder, src)
    590 				} else {
    591 					render("image", images[i], holder, src);
    592 				}
    593 			}
    594 		}
    595 	}
    596 	return app;
    597 };
    598 
    599 contentLoaded(win, function () {
    600 	if (window.addEventListener) {
    601 		window.addEventListener("resize", resizable_update, false);
    602 		window.addEventListener("orientationchange", resizable_update, false);
    603 	} else {
    604 		window.attachEvent("onresize", resizable_update)
    605 	}
    606 	preempted || app.run({});
    607 
    608 	if (typeof window.Turbolinks === "object") {
    609 		document.addEventListener("page:change", function() { app.run({}) })
    610 	}
    611 });
    612 if (typeof define === "function" && define.amd) {
    613 	define([], function () {
    614 		return app;
    615 	});
    616 }
    617 
    618 //github.com/davidchambers/Base64.js
    619 (function(){function t(t){this.message=t}var e="undefined"!=typeof exports?exports:this,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=Error(),t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-8*(a%1))){if(n=e.charCodeAt(a+=.75),n>255)throw new t("'btoa' failed");o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),1==e.length%4)throw new t("'atob' failed");for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(6&-2*a)):0)n=r.indexOf(n);return c})})();
    620 
    621 //getElementsByClassName polyfill
    622 document.getElementsByClassName||(document.getElementsByClassName=function(e){var t=document,n,r,i,s=[];if(t.querySelectorAll)return t.querySelectorAll("."+e);if(t.evaluate){r=".//*[contains(concat(' ', @class, ' '), ' "+e+" ')]",n=t.evaluate(r,t,null,0,null);while(i=n.iterateNext())s.push(i)}else{n=t.getElementsByTagName("*"),r=new RegExp("(^|\\s)"+e+"(\\s|$)");for(i=0;i<n.length;i++)r.test(n[i].className)&&s.push(n[i])}return s})
    623 
    624 //getComputedStyle polyfill
    625 window.getComputedStyle||(window.getComputedStyle=function(e){return this.el=e,this.getPropertyValue=function(t){var n=/(\-([a-z]){1})/g;return t=="float"&&(t="styleFloat"),n.test(t)&&(t=t.replace(n,function(){return arguments[2].toUpperCase()})),e.currentStyle[t]?e.currentStyle[t]:null},this})
    626 
    627 //http://javascript.nwbox.com/ContentLoaded by Diego Perini with modifications
    628 function contentLoaded(n,t){var l="complete",s="readystatechange",u=!1,h=u,c=!0,i=n.document,a=i.documentElement,e=i.addEventListener?"addEventListener":"attachEvent",v=i.addEventListener?"removeEventListener":"detachEvent",f=i.addEventListener?"":"on",r=function(e){(e.type!=s||i.readyState==l)&&((e.type=="load"?n:i)[v](f+e.type,r,u),!h&&(h=!0)&&t.call(n,null))},o=function(){try{a.doScroll("left")}catch(n){setTimeout(o,50);return}r("poll")};if(i.readyState==l)t.call(n,"lazy");else{if(i.createEventObject&&a.doScroll){try{c=!n.frameElement}catch(y){}c&&o()}i[e](f+"DOMContentLoaded",r,u),i[e](f+s,r,u),n[e](f+"load",r,u)}}
    629 
    630 //https://gist.github.com/991057 by Jed Schmidt with modifications
    631 function selector(a,b){var a=a.match(/^(\W)?(.*)/),b=b||document,c=b["getElement"+(a[1]?"#"==a[1]?"ById":"sByClassName":"sByTagName")],d=c.call(b,a[2]),e=[];return null!==d&&(e=d.length||0===d.length?d:[d]),e}
    632 
    633 //shallow object property extend
    634 function extend(a,b){
    635 	var c={};
    636 	for(var i in a){
    637 		if(a.hasOwnProperty(i)){
    638 			c[i]=a[i];
    639 		}
    640 	}
    641 	for(var i in b){
    642 		if(b.hasOwnProperty(i)){
    643 			c[i]=b[i];
    644 		}
    645 	}
    646 	return c
    647 }
    648 
    649 //hasOwnProperty polyfill
    650 if (!Object.prototype.hasOwnProperty)
    651     /*jshint -W001, -W103 */
    652     Object.prototype.hasOwnProperty = function(prop) {
    653 		var proto = this.__proto__ || this.constructor.prototype;
    654 		return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
    655 	}
    656     /*jshint +W001, +W103 */
    657 
    658 })(Holder, window);