PageSourceSearch

https://www.ing-bn.com/shared/html5/common.js?t=202208020105&g=202609211422

js ing-bn.com collected 2026-10-09 04:02:39 UTC 43,280 bytes, 1,368 lines download raw bytes

1/*
2 * jQuery scrollintoview() plugin and :scrollable selector filter
3 *
4 * Version 1.8 (14 Jul 2011)
5 * Requires jQuery 1.4 or newer
6 *
7 * Copyright (c) 2011 Robert Koritnik
8 * Licensed under the terms of the MIT license
9 * http://www.opensource.org/licenses/mit-license.php
10 */
11(function(f){var c={vertical:{x:false,y:true},horizontal:{x:true,y:false},both:{x:true,y:true},x:{x:true,y:false},y:{x:false,y:true}};var b={duration:"fast",direction:"both"};var e=/^(?:html)$/i;var g=function(k,j){j=j||(document.defaultView&&document.defaultView.getComputedStyle?document.defaultView.getComputedStyle(k,null):k.currentStyle);var i=document.defaultView&&document.defaultView.getComputedStyle?true:false;var h={top:(parseFloat(i?j.borderTopWidth:f.css(k,"borderTopWidth"))||0),left:(parseFloat(i?j.borderLeftWidth:f.css(k,"borderLeftWidth"))||0),bottom:(parseFloat(i?j.borderBottomWidth:f.css(k,"borderBottomWidth"))||0),right:(parseFloat(i?j.borderRightWidth:f.css(k,"borderRightWidth"))||0)};return{top:h.top,left:h.left,bottom:h.bottom,right:h.right,vertical:h.top+h.bottom,horizontal:h.left+h.right}};var d=function(h){var j=f(window);var i=e.test(h[0].nodeName);return{border:i?{top:0,left:0,bottom:0,right:0}:g(h[0]),scroll:{top:(i?j:h).scrollTop(),left:(i?j:h).scrollLeft()},scrollbar:{right:i?0:h.innerWidth()-h[0].clientWidth,bottom:i?0:h.innerHeight()-h[0].clientHeight},rect:(function(){var k=h[0].getBoundingClientRect();return{top:i?0:k.top,left:i?0:k.left,bottom:i?h[0].clientHeight:k.bottom,right:i?h[0].clientWidth:k.right}})()}};f.fn.extend({scrollintoview:function(j){j=f.extend({},b,j);j.direction=c[typeof(j.direction)==="string"&&j.direction.toLowerCase()]||c.both;var n="";if(j.direction.x===true){n="horizontal"}if(j.direction.y===true){n=n?"both":"vertical"}var l=this.eq(0);var i=l.closest(":scrollable("+n+")");if(i.length>0){i=i.eq(0);var m={e:d(l),s:d(i)};var h={top:m.e.rect.top-(m.s.rect.top+m.s.border.top),bottom:m.s.rect.bottom-m.s.border.bottom-m.s.scrollbar.bottom-m.e.rect.bottom,left:m.e.rect.left-(m.s.rect.left+m.s.border.left),right:m.s.rect.right-m.s.border.right-m.s.scrollbar.right-m.e.rect.right};var k={};if(j.direction.y===true){if(h.top<0){k.scrollTop=m.s.scroll.top+h.top}else{if(h.top>0&&h.bottom<0){k.scrollTop=m.s.scroll.top+Math.min(h.top,-h.bottom)}}}if(j.direction.x===true){if(h.left<0){k.scrollLeft=m.s.scroll.left+h.left}else{if(h.left>0&&h.right<0){k.scrollLeft=m.s.scroll.left+Math.min(h.left,-h.right)}}}if(!f.isEmptyObject(k)){if(e.test(i[0].nodeName)){i=f("html,body")}i.animate(k,j.duration).eq(0).queue(function(o){f.isFunction(j.complete)&&j.complete.call(i[0]);o()})}else{f.isFunction(j.complete)&&j.complete.call(i[0])}}return this}});var a={auto:true,scroll:true,visible:false,hidden:false};f.extend(f.expr[":"],{scrollable:function(k,i,n,h){var m=c[typeof(n[3])==="string"&&n[3].toLowerCase()]||c.both;var l=(document.defaultView&&document.defaultView.getComputedStyle?document.defaultView.getComputedStyle(k,null):k.currentStyle);var o={x:a[l.overflowX.toLowerCase()]||false,y:a[l.overflowY.toLowerCase()]||false,isRoot:e.test(k.nodeName)};if(!o.x&&!o.y&&!o.isRoot){return false}var j={height:{scroll:k.scrollHeight,client:k.clientHeight},width:{scroll:k.scrollWidth,client:k.clientWidth},scrollableX:function(){return(o.x||o.isRoot)&&this.width.scroll>this.width.client},scrollableY:function(){return(o.y||o.isRoot)&&this.height.scroll>this.height.client}};return m.y&&j.scrollableY()||m.x&&j.scrollableX()}})})(jQuery);
12
13
14if (!Function.prototype.bind) {
15	Function.prototype.bind = function(oThis) {
16		if (typeof this !== 'function')
17			throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
18		var aArgs   = Array.prototype.slice.call(arguments, 1),
19			fToBind = this,
20			fNOP    = function() {},
21			fBound  = function() {
22				return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,
23					aArgs.concat(Array.prototype.slice.call(arguments)));
24			};
25		fNOP.prototype = this.prototype;
26		fBound.prototype = new fNOP();
27		return fBound;
28	};
29}
30
31(function () {
32	if (!self.CB5) self.CB5 = {};
33	var util = {};
34	CB5.config = {};
35	CB5.util = util;
36	CB5.plugin = {};
37	CB5.emailReg = /^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-zöäëß0-9](?:[a-zöäëß0-9-]*[a-zöäëß0-9])?\.)+(?:[a-z]{2}|aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|xxx)$/i;
38
39	CB5.isTouch = /iPad|iPhone|iPod|Android/.test(navigator.userAgent);
40	CB5.isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
41
42	CB5.vendorCss = function(o, prop, value) {
43		o[prop] = value;
44		prop = prop.charAt(0).toUpperCase() + prop.substr(1);
45		o['Webkit' + prop] = o['Moz' + prop] = o['ms' + prop] = o['O' + prop] = value;
46		return o;
47	};
48	CB5.scrollTop = function () {return Math.max($('body').scrollTop(), $('html').scrollTop());};
49
50
51	CB5.getRealPath = function (path)
52	{
53		var map = {
54			user:'files',
55			shared:'shared/html5',
56			resource:CB5.config.rootUrl + 'action/resource',
57			thumb:CB5.config.rootUrl + 'action/thumb',
58			search: CB5.config.rootUrl + 'action/search',
59			topbanner: CB5.config.rootUrl + 'action/topbanner',
60			library: 'lib/browse'
61		};
62		var a = path.split('://');
63		return (a[0] in map) ? map[a[0]] + '/' + a[1] : path;
64	};
65
66
67	var Class = function () {};
68	Class.extend = function (config) {
69		var proto = new this();
70		for (var name in config)
71			proto[name] = config[name];
72		var Cls = config.init;
73		Cls.prototype = proto;
74		Cls.extend = this.extend;
75
76		proto.constructor = Cls;
77		proto.super = this.prototype;
78		return Cls;
79	};
80	util.Class = Class;
81
82
83	var loadScriptMap = {};
84	util.loadScript = function(url, callback) {
85
86		if (url instanceof Array) {
87			var cnt = url.length;
88			url.forEach(function (u) {
89				util.loadScript(u, function () {
90					cnt --;
91					if (cnt == 0) callback();
92				});
93			});
94			return;
95		}
96
97		if (loadScriptMap[url]) {
98			if (loadScriptMap[url] == 'loaded') callback();
99			else loadScriptMap[url].push(callback);
100			return;
101		}
102
103		var script = document.createElement('script');
104		loadScriptMap[url] = [callback];
105		script.type = 'text/javascript';
106		if (callback) script.addEventListener('load', function () {
107			loadScriptMap[url].forEach(function (cb) {
108				cb();
109			});
110			loadScriptMap[url] = 'loaded';
111		});
112		script.src = url;
113		document.body.appendChild(script);
114	};
115	CB5.loadScript = util.loadScript;
116
117
118
119	util.noiseFill = function (color, color2, intensity, opacity) {
120
121		var n = parseInt('0x' + color);
122		var argb = {a: (0xFF000000 & n) >>> 24, r: (0xFF0000 & n) >>> 16,g: (0xFF00 & n) >>> 8,b: 0xFF & n};
123
124		var size = 50;
125		var canvas  = document.createElement('canvas');
126		canvas.width = canvas.height = size;
127
128		var ctx = canvas.getContext('2d');
129		ctx.fillStyle = util.Color.toRgba(color, true);
130		ctx.fillRect(0, 0, size, size);
131		var	imgData = ctx.getImageData(0, 0, size, size),
132			numPixels = Math.round( intensity * Math.pow(size, 2) );
133
134		n = parseInt('0x' + color2);
135		var noiseArgb = {a: (0xFF000000 & n) >>> 24, r: (0xFF0000 & n) >>> 16,g: (0xFF00 & n) >>> 8,b: 0xFF & n};
136
137		// Add color to random pixels in the canvas
138		while (numPixels--) { // Read about the double bitwise NOT trick here: goo.gl/6DPpt
139			var x = ~~(Math.random()*canvas.width),
140				y = ~~(Math.random()*canvas.height),
141				index = (x + y * imgData.width) * 4;
142
143			var op = Math.random() * opacity * noiseArgb.a/255;
144			imgData.data[index] = ~~(argb.r*(1-op) + noiseArgb.r*op);//R
145			imgData.data[index+1] = ~~(argb.g*(1-op) + noiseArgb.g*op);//G
146			imgData.data[index+2] = ~~(argb.b*(1-op) + noiseArgb.b*op);//B
147		}
148
149		ctx.putImageData(imgData, 0, 0);
150		return canvas.toDataURL('image/png');
151	};
152
153
154	util.round4 = function (n) {
155		return Math.round(n * 10000) / 10000;
156	};
157
158	// -----------------------------------------------------------------------
159	// Drawing on canvas
160	// -----------------------------------------------------------------------
161	util.Drawing = {
162
163		drawStar: function(g, x, y, points,
164						   innerRadiusX,
165						   innerRadiusY,
166						   outerRadiusX,
167						   outerRadiusY,
168						   angle)
169		{
170			var count = Math.abs(points);
171
172			if (count > 2)
173			{
174				var step = (Math.PI * 2) / points;
175				var halfStep = step / 2;
176
177				var startAngle = (angle / 180) * Math.PI;
178				g.moveTo(x + (Math.cos(startAngle) * outerRadiusX), y - (Math.sin(startAngle) * outerRadiusY));
179
180				var dx;
181				var dy;
182
183				// draw lines
184				for (var n = 1; n <= count; n++)
185				{
186					dx = x + Math.cos(startAngle + (step * n) - halfStep) * innerRadiusX;
187					dy = y - Math.sin(startAngle + (step * n) - halfStep) * innerRadiusY;
188					g.lineTo(dx, dy);
189					dx = x + Math.cos(startAngle + (step * n)) * outerRadiusX;
190					dy = y - Math.sin(startAngle + (step * n)) * outerRadiusY;
191					g.lineTo(dx, dy);
192				}
193			}
194		}, //end drawStar
195
196		drawBurst : function(g, x, y, sides, innerRadiusX, innerRadiusY, outerRadiusX, outerRadiusY, angle)
197		{
198			if (sides < 3) return;
199
200			var step = (Math.PI * 2) / sides;
201			var halfStep = step / 2;
202			var qtrStep = step / 4;
203			var start = (angle / 180) * Math.PI;
204			g.moveTo(x + (Math.cos(start) * outerRadiusX), y - (Math.sin(start) * outerRadiusY));
205
206			var cx;
207			var cy;
208			var dx;
209			var dy;
210
211			for (var n = 1; n <= sides; n++)
212			{
213				cx = x + Math.cos(start + (step * n) - (qtrStep * 3)) * (innerRadiusX / Math.cos(qtrStep));
214				cy = y - Math.sin(start + (step * n) - (qtrStep * 3)) * (innerRadiusY / Math.cos(qtrStep));
215				dx = x + Math.cos(start + (step * n) - halfStep) * innerRadiusX;
216				dy = y - Math.sin(start + (step * n) - halfStep) * innerRadiusY;
217				g.curveTo(cx, cy, dx, dy);
218				cx = x + Math.cos(start + (step * n) - qtrStep) * (innerRadiusX / Math.cos(qtrStep));
219				cy = y - Math.sin(start + (step * n) - qtrStep) * (innerRadiusY / Math.cos(qtrStep));
220				dx = x + Math.cos(start + (step * n)) * outerRadiusX;
221				dy = y - Math.sin(start + (step * n)) * outerRadiusY;
222				g.curveTo(cx, cy, dx, dy);
223			}
224		}, //end draw burst
225
226		drawArc : function(g, x, y, radiusX, radiusY, arc, startAngle)
227		{
228			g.moveTo(x, y);
229			if (Math.abs(arc)>360)
230				arc = 360;
231			var segs = Math.ceil(Math.abs(arc) / 45);
232
233			var segAngle = arc / segs;
234
235			var theta = -(segAngle / 180) * Math.PI;
236			var angle = -(startAngle / 180) * Math.PI;
237			var ax = x - Math.cos(angle) * radiusX;
238			var ay = y - Math.sin(angle) * radiusY;
239			if (segs > 0)
240			{
241				var angleMid;
242				var bx;
243				var by;
244				var cx;
245				var cy;
246				for (var i = 0; i < segs; i++)
247				{
248					angle += theta;
249					angleMid = angle - (theta / 2);
250					bx = ax + Math.cos(angle) * radiusX;
251					by = ay + Math.sin(angle) * radiusY;
252					cx = ax + Math.cos(angleMid) * (radiusX / Math.cos(theta / 2));
253					cy = ay + Math.sin(angleMid) * (radiusY / Math.cos(theta / 2));
254					g.curveTo(cx, cy, bx, by);
255				}
256			}
257			//return new Point(bx, by);
258		}, //end drawArc
259
260		drawWedge : function (g, x, y, startAngle, arc, radiusX, radiusY)
261		{
262			g.moveTo(x, y);
263			if (arguments.length == 6) radiusY = radiusX;
264			var segAngle, theta, angle, angleMid, segs, ax, ay, bx, by, cx, cy;
265			if (Math.abs(arc) > 360) arc = 360;
266			segs = Math.ceil(Math.abs(arc) / 45);
267			segAngle = arc / segs;
268			theta = -(segAngle / 180) * Math.PI;
269			angle = -(startAngle / 180) * Math.PI;
270			if (segs > 0)
271			{
272				ax = x + Math.cos(startAngle / 180 * Math.PI) * radiusX;
273				ay = y + Math.sin(-startAngle / 180 * Math.PI) * radiusY;
274				g.lineTo(ax, ay);
275				for (var i = 0; i < segs; i++)
276				{
277					angle += theta;
278					angleMid = angle - (theta / 2);
279					bx = x + Math.cos(angle) * radiusX;
280					by = y + Math.sin(angle) * radiusY;
281					cx = x + Math.cos(angleMid) * (radiusX / Math.cos(theta / 2));
282					cy = y + Math.sin(angleMid) * (radiusY / Math.cos(theta / 2));
283					g.curveTo(cx, cy, bx, by);
284				}
285				// close the wedge by drawing a line to the center
286				g.lineTo(x, y);
287			}
288		}, //end drawWedge
289
290		drawPoly: function(g, x, y, sides, radiusX, radiusY, angle)
291		{
292			var count = Math.abs(sides);
293			if (count > 2)
294			{
295				var step, startAngle, dx, dy;
296				step = (Math.PI * 2) / sides;
297				startAngle = (angle / 180) * Math.PI;
298				g.moveTo(x + (Math.cos(startAngle) * radiusX), y - (Math.sin(startAngle) * radiusY));
299				for (var n = 1; n <= count; n++)
300				{
301					dx = x + Math.cos(startAngle + (step * n)) * radiusX;
302					dy = y - Math.sin(startAngle + (step * n)) * radiusY;
303					g.lineTo(dx, dy);
304				}
305			}
306		}, //end drawPoly
307
308		drawGear : function (g, x, y, sides,
309							 innerRadiusX,
310							 innerRadiusY,
311							 outerRadiusX,
312							 outerRadiusY,
313							 angle,
314							 holeSides,
315							 holeRadiusX,
316							 holeRadiusY)
317		{
318			sides = Math.round(sides);
319			holeSides = Math.round(holeSides);
320			if (sides > 2)
321			{
322				// init vars
323				var step;
324				var qtrStep;
325				var startAngle;
326				var dx;
327				var dy;
328
329				step = (Math.PI * 2) / sides;
330				qtrStep = step / 4;
331
332				startAngle = (angle / 180) * Math.PI;
333				g.moveTo(x + (Math.cos(startAngle) * outerRadiusX), y - (Math.sin(startAngle) * outerRadiusY));
334
335				// draw lines
336				for (var n = 1; n <= sides; n++)
337				{
338					dx = x + Math.cos(startAngle + (step * n) - (qtrStep * 3)) * innerRadiusX;
339					dy = y - Math.sin(startAngle + (step * n) - (qtrStep * 3)) * innerRadiusY;
340					g.lineTo(dx, dy);
341					dx = x + Math.cos(startAngle + (step * n) - (qtrStep * 2)) * innerRadiusX;
342					dy = y - Math.sin(startAngle + (step * n) - (qtrStep * 2)) * innerRadiusY;
343					g.lineTo(dx, dy);
344					dx = x + Math.cos(startAngle + (step * n) - qtrStep) * outerRadiusX;
345					dy = y - Math.sin(startAngle + (step * n) - qtrStep) * outerRadiusY;
346					g.lineTo(dx, dy);
347					dx = x + Math.cos(startAngle + (step * n)) * outerRadiusX;
348					dy = y - Math.sin(startAngle + (step * n)) * outerRadiusY;
349					g.lineTo(dx, dy);
350				}
351
352				if (holeSides > 2)
353				{
354					if(!holeRadiusX)
355						holeRadiusX = innerRadiusX / 3;
356
357					if(!holeRadiusY)
358						holeRadiusY = innerRadiusY / 3;
359
360					step = (Math.PI * 2) / holeSides;
361					g.moveTo(x + (Math.cos(startAngle) * holeRadiusX), y - (Math.sin(startAngle) * holeRadiusY));
362					for (var m = holeSides; m >= 1; m--)
363					{
364						dx = x + Math.cos(startAngle + (step * m)) * holeRadiusX;
365						dy = y - Math.sin(startAngle + (step * m)) * holeRadiusY;
366						g.lineTo(dx, dy);
367					}
368				}
369			}
370		},//end drawGear
371
372        drawDonut: function(g, x, y,
373                            innerRadiusX,
374                            innerRadiusY,
375                            outerRadiusX,
376                            outerRadiusY) {
377            g.ctx.arc(x, y, outerRadiusX, 0, 2 * Math.PI);
378            g.ctx.arc(x, y, innerRadiusX, 0, 2 * Math.PI, 1);
379
380        }, //end drawDonut
381        drawMask: function(g, type, ox, oy, osx, osy, ix, iy, isx, isy) {
382            shapes = type.split('-');
383            g.drawShape(shapes[0], ox, oy, osx, osy, false);
384            g.drawShape(shapes[1], ix, iy, isx, isy, true);
385        } //end drawFrame
386
387	};
388
389	// -----------------------------------------------------------------------
390	// Color functions
391	// -----------------------------------------------------------------------
392	(function() {
393
394		var Color = CB5.Color = util.Color = {};
395
396		/*private*/
397		function any2rgb(c) {
398			if (/^rgba/.test(c)) {
399				var a = c.substr(5).substr(0, c.length-6).split(',');
400				return [Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3])];
401			}
402			if (/^rgb\(/.test(c)) {
403				var a = c.slice(4, -1).split(',');
404				return [Number(a[0]), Number(a[1]), Number(a[2]), 1];
405			}
406			return any2rgb(Color.toRgba(c));
407		}
408		Color.toArray = function (c) {
409			return any2rgb(c);
410		};
411		Color.toRgba = function (ahex, pad0es) {
412			if (!ahex) return('rgba(0,0,0,0)');
413			if (typeof ahex == 'number')
414				ahex = ('00000000' + ahex.toString(16)).slice(-8);
415			if (ahex.slice(0,3) == 'rgb') return Color.toRgba(Color.toAHEX(ahex));
416			if(ahex.charAt(0)=='#') ahex = ahex.substr(1);
417			if (pad0es && ahex.length < 8) ahex = ('00000000'+ahex).substr(-8);
418			if (ahex.length == 6) ahex = 'ff' + ahex;
419			if (ahex.length != 8) return('rgba(0,0,0,0)');
420			return 'rgba('+
421			parseInt('0x' + ahex.substr(2, 2)) + ',' +
422			parseInt('0x' + ahex.substr(4, 2)) + ',' +
423			parseInt('0x' + ahex.substr(6, 2)) + ',' +
424			Math.round(parseInt('0x' + ahex.substr(0, 2))/2.55)/100 + ')';
425		};
426		Color.toAHEX = function (any) {
427			var a = any2rgb(any);
428			return hex2(a[3]*255) + hex2(a[0]) + hex2(a[1]) + hex2(a[2]);
429		};
430		Color.mixColors = mixColors;
431		function mixColors(c1, c2, p, outFormat) {
432			var v1 = any2rgb(c1);
433			var v2 = any2rgb(c2);
434			var v3 = [v1[0]*p+v2[0]*(1-p), v1[1]*p+v2[1]*(1-p), v1[2]*p+v2[2]*(1-p), v1[3]*p+v2[3]*(1-p)];
435			if (outFormat == 'uhex')
436				return hex2(v3[3]*255) + hex2(v3[0]) + hex2(v3[1]) + hex2(v3[2]);
437			return 'rgba('+Math.round(v3[0])+','+Math.round(v3[1])+','+Math.round(v3[2])+','+v3[3]+')';
438		}
439
440		function hex2(v) {
441			return ('00' + Math.round(v).toString(16)).substr(-2);
442		}
443
444		Color.pad0 = function (color) {
445			return ('00000000' + color).substr(-8);
446		};
447		Color.getAlpha = function (rgba) {
448			return parseFloat(rgba.substr(rgba.lastIndexOf(',')+1));
449		};
450	})();
451
452
453
454})();
455
456
457
458
459
460(function () {
461// -----------------------------------------------------------------------
462// PACKAGE GEOM
463// -----------------------------------------------------------------------
464	var debug = self.console ? console[console.debug ? 'debug' : 'log'].bind(console) : $.noop;
465
466	var geom = {};
467	var Class = CB5.util.Class;
468	CB5.util.geom = geom;
469
470	/** @class */
471	geom.Point = Class.extend({
472		x: 0, y: 0,
473		/** @constructs */
474		init: function (x, y) {
475			if (arguments.length == 0) return;
476			this.x = Number(x);
477			this.y = Number(y);
478		},
479		/**
480		 * @returns {geom.Point}
481		 */
482		clone: function () {
483			return new geom.Point(this.x, this.y);
484		},
485		put: function (x, y) {
486			this.x = x;
487			this.y = y;
488		},
489		/**
490		 * @param {geom.Point} p
491		 * @returns {geom.Point} new Point
492		 */
493		subtract: function (p) {
494			this.x -= p.x;
495			this.y -= p.y;
496			return this;
497		},
498		add: function (p) {
499			this.x += p.x;
500			this.y += p.y;
501			return this;
502		},
503		scale: function (c) {
504			this.x *= c;
505			this.y *= c;
506			return this;
507		},
508		size: function () {
509			return Math.sqrt(this.x*this.x + this.y*this.y);
510		},
511		limit: function (minX, minY, maxX, maxY) {
512			this.x = Math.max(minX, Math.min(maxX, this.x));
513			this.y = Math.max(minY, Math.min(maxY, this.y));
514			return this;
515		},
516		toString: function () {
517			return '(' + this.x + ',' + this.y + ')';
518		}
519	});
520
521	/** @class */
522	geom.Matrix = Class.extend({
523		a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0,
524		/** @constructs
525		 * @param {String=} data
526		 */
527		init: function (data) {
528			if (arguments.length == 0) return;
529			if (arguments.length > 3) {
530				this.a = Number(arguments[0]);
531				this.b = Number(arguments[1]);
532				this.c = Number(arguments[2]);
533				this.d = Number(arguments[3]);
534				if (arguments[4]) this.tx = Number(arguments[4]);
535				if (arguments[5]) this.ty = Number(arguments[5]);
536				return;
537			}
538			var a = data.split(',');
539			this.a = Number(a[0]);
540			this.b = Number(a[1]);
541			this.c = Number(a[2]);
542			this.d = Number(a[3]);
543			this.tx = Number(a[4]);
544			this.ty = Number(a[5]);
545		},
546
547		/** @returns geom.Matrix */
548		invert: function () {
549			var det = this.a * this.d - this.b * this.c;
550			var tx = this.tx, a = this.a;
551			this.tx = (this.c * this.ty - this.d * tx) / det;
552			this.ty = (this.b * tx - this.a * this.ty) / det;
553
554			this.a = this.d / det;
555			this.b = -this.b / det;
556			this.c = -this.c / det;
557			this.d = a / det;
558			return this;
559		},
560
561		/** @param {geom.Point} p
562		 *  @returns geom.Point */
563		transformPoint: function (p) {
564			var x = p.x, y = p.y;
565			p.x = this.a * x + this.c * y + this.tx;
566			p.y = this.b * x + this.d * y + this.ty;
567			return p;
568		},
569
570		/**
571		 * @return {geom.Matrix}
572		 */
573		normalize: function () {
574			var len = Math.sqrt(this.a * this.a + this.b * this.b);
575			this.a /= len;
576			this.b /= len;
577			len = Math.sqrt(this.c * this.c + this.d * this.d);
578			this.c /= len;
579			this.d /= len;
580			return this;
581		},
582
583		isUnit: function () {
584			return this.a == 1 && this.b == 0 && this.c == 0 && this.d == 1;
585		},
586
587		round4: function () {
588			this.a = Math.round(this.a * 10000) / 10000;
589			this.b = Math.round(this.b * 10000) / 10000;
590			this.c = Math.round(this.c * 10000) / 10000;
591			this.d = Math.round(this.d * 10000) / 10000;
592			this.tx = Math.round(this.tx * 10000) / 10000;
593			this.ty = Math.round(this.ty * 10000) / 10000;
594			return this;
595		},
596
597		/**
598		 * @param {geom.Matrix} m
599		 * @return {geom.Matrix}
600		 */
601		concat: function (m) {
602			var a = this.a,
603				b = this.b,
604				c = this.c,
605				d = this.d,
606				tx = this.tx;
607			this.a = m.a * a + m.c * b;
608			this.b = m.b * a + m.d * b;
609			this.c = m.a * c + m.c * d;
610			this.d = m.b * c + m.d * d;
611			this.tx = m.tx + m.c * this.ty + m.a * tx;
612			this.ty = m.ty + m.d * this.ty + m.b * tx;
613			return this;
614		},
615
616		/**
617		 * Applies delta matrix in place
618		 * @param {geom.Matrix} delta
619		 * @param {geom.Matrix} space
620		 * @returns {geom.Matrix}
621		 */
622		applyDelta: function (delta, space) {
623			return this.concat(space.clone().invert()).concat(delta).concat(space);
624		},
625
626		scale: function (sx, sy, noTranslate) {
627			if (arguments.length == 0) {
628				return new geom.Point(
629					Math.sqrt(this.a * this.a + this.b * this.b),
630					Math.sqrt(this.c * this.c + this.d * this.d));
631			}
632			if (arguments.length == 1) sy = sx;
633			this.a *= sx;
634			this.b *= sy;
635			this.c *= sx;
636			this.d *= sy;
637			if (!noTranslate) {
638				this.tx *= sx;
639				this.ty *= sy;
640			}
641			return this;
642		},
643
644		rotate: function (rad) {
645			var m = new geom.Matrix();
646			m.a = Math.cos(rad);
647			m.c = -Math.sin(rad);
648			m.b = Math.sin(rad);
649			m.d = Math.cos(rad);
650			this.concat(m);
651			return this;
652		},
653
654		/** @returns geom.Matrix */
655		translate: function (tx, ty) {
656			this.tx += Number(tx);
657			this.ty += Number(ty);
658			return this;
659		},
660
661		put: function (tx, ty) {
662			this.tx = tx;
663			this.ty = ty;
664			return this;
665		},
666
667		pos: function () {
668			return new geom.Point(this.tx, this.ty);
669		},
670
671		/** @param {Number=} d */
672		getWidth: function (d) {
673			if (d == null) d = 100;
674			return Math.sqrt(this.a * this.a + this.b * this.b) * d;
675		},
676
677		/** @param {Number=} d */
678		getHeight: function (d) {
679			if (d == null) d = 100;
680			return Math.sqrt(this.c * this.c + this.d * this.d) * d;
681		},
682
683		setHeight: function (h) {
684			var delta = new geom.Matrix();
685			delta.d = h / this.getHeight();
686			return this.copy(delta.concat(this));
687		},
688
689		setWidth: function (w) {
690			var delta = new geom.Matrix();
691			delta.a = w / this.getWidth();
692			return this.copy(delta.concat(this));
693		},
694
695		/**
696		 * @return {geom.Matrix}
697		 */
698		clone: function () {
699			return new geom.Matrix(this.serialize());
700		},
701
702		copy: function (m) {
703			this.a = m.a;
704			this.b = m.b;
705			this.c = m.c;
706			this.d = m.d;
707			this.tx = m.tx;
708			this.ty = m.ty;
709			return this;
710		},
711
712		serialize: function () {
713			this.a = Math.round(this.a*1e10)/1e10;
714			this.b = Math.round(this.b*1e10)/1e10;
715			this.c = Math.round(this.c*1e10)/1e10;
716			this.d = Math.round(this.d*1e10)/1e10;
717			this.tx = Math.round(this.tx*1e10)/1e10;
718			this.ty = Math.round(this.ty*1e10)/1e10;
719			return [this.a, this.b, this.c, this.d, this.tx, this.ty].join(',');
720		},
721
722		toString: function () {
723			return '[' + this.serialize() + ']';
724		},
725
726		equals: function (m) {
727			return Math.abs(m.a - this.a) < 1e-4 &&
728			Math.abs(m.b - this.b) < 1e-4 &&
729			Math.abs(m.c - this.c) < 1e-4 &&
730			Math.abs(m.d - this.d) < 1e-4 &&
731			Math.abs(m.tx - this.tx) < 1e-4 &&
732			Math.abs(m.ty - this.ty) < 1e-4;
733		}
734
735
736	});
737
738	geom.Rectangle = Class.extend({
739		left: 0,
740		top: 0,
741		right: 0,
742		bottom: 0,
743		/** @constructs */
744		init: function (left, top, right, bottom) {
745			if (arguments.length == 0) return;
746			if (arguments.length == 1) {
747				var rect = left;
748				this.left = rect.left;
749				this.top = rect.top;
750				this.right = rect.right;
751				this.bottom = rect.bottom;
752				return;
753			}
754			this.left = Math.min(left, right);
755			this.top = Math.min(top, bottom);
756			this.right = Math.max(left, right);
757			this.bottom = Math.max(top, bottom);
758		},
759		clone: function () {
760			return new geom.Rectangle(this.left, this.top, this.right, this.bottom);
761		},
762		scale: function (p) {
763			this.left *= p.x;
764			this.top *= p.y;
765			this.right *= p.x;
766			this.bottom *= p.y;
767			return this;
768		},
769		width: function () {
770			return this.right - this.left;
771		},
772		height: function () {
773			return this.bottom - this.top;
774		},
775		/** contains rectangle or point */
776		contains: function (r) {
777			if ('bottom' in r)
778				return this.left < r.left && this.top < r.top && this.right > r.right && this.bottom > r.bottom;
779			return r.x > this.left && r.y > this.top && r.x < this.right && r.y < this.bottom;
780		},
781		restrict: function (r) {
782			if (this.left < r.left) this.left = r.left;
783			if (this.top < r.top) this.top = r.top;
784			if (this.left > r.right - 1) this.left = r.right - 1;
785			if (this.top > r.bottom - 1) this.top = r.bottom - 1;
786			if (this.bottom > r.bottom) this.bottom = r.bottom;
787			if (this.right > r.right) this.right = r.right;
788			if (this.bottom < r.top + 1) this.bottom = r.top + 1;
789			if (this.right < r.left + 1) this.right = r.left + 1;
790		},
791		extend: function (rect) {
792			this.left > rect.left && (this.left = rect.left);
793			this.top > rect.top && (this.top = rect.top);
794			this.right < rect.right && (this.right = rect.right);
795			this.bottom < rect.bottom && (this.bottom = rect.bottom);
796		},
797		extendP: function (p) {
798			this.left > p.x && (this.left = p.x);
799			this.top > p.y && (this.top = p.y);
800			this.right < p.x && (this.right = p.x);
801			this.bottom < p.y && (this.bottom = p.y);
802		},
803		translate: function (dx, dy) {
804			this.left += dx;
805			this.top += dy;
806			this.right += dx;
807			this.bottom += dy;
808		},
809		css: function () {
810			return {left: this.left, top: this.top, width: this.right - this.left, height: this.bottom - this.top};
811		},
812		toString: function () {
813			return '[geom.Rectangle ' + [this.left, this.top, this.right, this.bottom] + ']';
814		}
815	});
816
817	var util = CB5.util;
818	$.fn.matrix = function (m) {
819		if (arguments.length == 0) {
820			var sm = this.css('transform');
821			if (sm && sm.indexOf('matrix') == 0) {
822				sm = sm.substring(sm.indexOf('(') + 1, sm.indexOf(')'));
823				m = new geom.Matrix(sm);
824			} else
825				m = new geom.Matrix();
826			var top = parseFloat(this.css('top'));
827			if (!isNaN(top)) {
828				m.ty += top;
829				m.tx += parseFloat(this.css('left'));
830			}
831			return m;
832		}
833
834		m = m.clone().round4();
835
836		this.css('transform-origin', '0px 0px');
837		if (m.isUnit()) {
838			this.css({top: m.ty, left: m.tx});
839			this.css('transform', '');
840		} else {
841			var str = 'matrix(' + m.a + ',' + m.b + ',' + m.c + ',' + m.d + ',' + m.tx + ',' + m.ty + ')';
842			this.css({top: '', left: ''});
843			this.css({transform: str});
844		}
845	};
846
847	/** @returns {geom.Point} */
848	util.getEventPosition = function(evt) {
849		if (evt.originalEvent) evt = evt.originalEvent;
850		var t = evt.changedTouches || evt.touches;
851		t = t ? t[0] : evt;
852		var zoom = document.body.style.zoom ? parseFloat(document.body.style.zoom) : 1;
853		return new geom.Point(t.pageX/zoom, t.pageY/zoom);
854	};
855
856	/**
857	 * $.parseParams - parse query string paramaters into an object.
858	 */
859	(function() {
860		var re = /([^&=]+)=?([^&]*)/g;
861		var decodeRE = /\+/g;  // Regex for replacing addition symbol with a space
862		var decode = function (str) {return decodeURIComponent( str.replace(decodeRE, " ") );};
863		util.parseParams = function(query) {
864			var params = {}, e;
865			while ( e = re.exec(query) ) {
866				var k = decode( e[1] ), v = decode( e[2] );
867				if (k.substring(k.length - 2) === '[]') {
868					k = k.substring(0, k.length - 2);
869					(params[k] || (params[k] = [])).push(v);
870				}
871				else params[k] = v;
872			}
873			return params;
874		};
875	})();
876
877
878	$.fn.cbDraggable = function (opts) {
879		var $me = this, y0, y;
880		opts = $.extend({
881			dir: 'y',//or x
882			max: 10000,
883			min: -10000,
884			drag: $.noop,
885			stop: $.noop,
886			cancel: null,
887			linkMul: 1,
888			id:'',
889			preventDefault: true
890		}, opts);
891
892		var css = opts.dir == 'y' ? 'top' : 'left';
893		var moved = false;
894
895		var p0;
896		var lastY = 0;
897
898		$me.on('mousedown touchstart', function (e) {
899			opts.preventDefault && e.preventDefault();
900			if (opts.cancel && $(e.target).is(opts.cancel)) return;
901			p0 = util.getEventPosition(e);
902			y0 = parseInt($me.css(css)) - p0[opts.dir];
903			$(self).on('mousemove.cb-drag touchmove.cb-drag', move).on('mouseup.cb-drag touchend.cb-drag', up);
904			$me.addClass('dragging');
905			moved = false;
906		});
907
908		var dy = 0;//parseInt(self.getComputedStyle($me[0]).marginTop);
909
910		function move(e) {
911			opts.preventDefault && e.preventDefault();
912			var p = util.getEventPosition(e);
913			y = Math.max(Math.min(y0 + p[opts.dir], opts.max-dy), opts.min-dy);
914			$me.attr('data-drag-dir', y > lastY ? '1' : '0');
915			lastY = y;
916			$me.css(css, y + 'px');
917			$me.find('> .drag-value').text(y*opts.linkMul);
918			//return false in drag to cancel drag
919			var ret = opts.drag(y+dy, p.subtract(p0));
920			moved = true;
921			if (ret === false) up();
922		}
923		function up(e) {
924			$(self).off('.cb-drag');
925			$me.removeClass('dragging');
926			if (e && !moved && opts.click) opts.click();
927			if (!e || !moved) return;
928			opts.stop(y+dy, opts.id);
929		}
930	};
931
932
933	function noiseFill(color, color2, intensity, opacity) {
934
935		var n = parseInt('0x' + color);
936		var argb = {a: (0xFF000000 & n) >>> 24, r: (0xFF0000 & n) >>> 16,g: (0xFF00 & n) >>> 8,b: 0xFF & n};
937
938		var size = 50;
939		var canvas  = document.createElement('canvas');
940		canvas.width = canvas.height = size;
941
942		var ctx = canvas.getContext('2d');
943		ctx.fillStyle = util.Color.toRgba(color, true);
944		ctx.fillRect(0, 0, size, size);
945		var	imgData = ctx.getImageData(0, 0, size, size),
946			numPixels = Math.round( intensity * Math.pow(size, 2) )//, maxAlpha = 255 * opacity;
947
948		var n = parseInt('0x' + color2);
949		var noiseArgb = {a: (0xFF000000 & n) >>> 24, r: (0xFF0000 & n) >>> 16,g: (0xFF00 & n) >>> 8,b: 0xFF & n};
950
951		// Add color to random pixels in the canvas
952		while (numPixels--) { // Read about the double bitwise NOT trick here: goo.gl/6DPpt
953			var x = ~~(Math.random()*canvas.width),
954				y = ~~(Math.random()*canvas.height),
955				index = (x + y * imgData.width) * 4;
956
957			var op = Math.random() * opacity * noiseArgb.a/255;
958			imgData.data[index] = ~~(argb.r*(1-op) + noiseArgb.r*op);//R
959			imgData.data[index+1] = ~~(argb.g*(1-op) + noiseArgb.g*op);//G
960			imgData.data[index+2] = ~~(argb.b*(1-op) + noiseArgb.b*op);//B
961		}
962
963		ctx.putImageData(imgData, 0, 0);
964		return canvas.toDataURL('image/png');
965	}
966
967
968	util.fillStyleCss = function (style) {
969		var css = [];
970		function gradStops() {
971			var aStops = [];
972			var colors = [];
973			var ratios = style.ratios;
974			var aColors = style.colors;
975			for (var i=0; i<aColors.length; i++) {
976				var color = util.Color.toRgba(aColors[i], true);
977				colors.push(color);
978				var pos = Math.round(ratios[i]/255*100*10000)/10000;
979				aStops.push(color + ' ' + pos + '%');
980			}
981			return aStops.join(',');
982		}
983
984		if (style.type == 'solid')
985			css.push({background: util.Color.toRgba(style.color, true)});
986		else if (style.type == 'linear') {
987			var rot = Number(style.rotation);
988			var angle = -Math.round(rot / Math.PI * 180);
989			var stdAngle = 90 - angle;
990			css.push({background: 'linear-gradient('+stdAngle+'deg, '+gradStops()+')'});
991		} else if (style.type == 'bitmap') {
992			var repeat = style.repeat == 'fill' ? 'no-repeat' : style.repeat;
993			var align = style.align ? style.align : 'center top';
994			var color = style.solid ? util.Color.toRgba(style.solid, true) : '';
995			css.push({background: color + ' url(' + CB5.getRealPath(style.src) + ') ' + align + ' ' + repeat});
996			css.push({'background-size': style.repeat == 'fill' ? 'cover' : 'auto'});
997		} else if (style.type == 'radial') {
998			var pos = (Number(style.translatex)+.5)*100 + '% ' + (Number(style.translatey)+.5)*100 + '%';
999			var stops =	gradStops();
1000			css.push({background: 'radial-gradient(ellipse farthest-side at '+pos+','+stops+')'});
1001			css.push({background: '-moz-radial-gradient('+pos+',ellipse farthest-side,'+stops+')'});
1002			css.push({background: '-webkit-radial-gradient('+pos+',ellipse farthest-side,'+stops+')'});
1003		} else if (style.type == 'none') {
1004			css.push({background: 'none'});
1005		} else if (style.type == 'noise') {
1006			css.push({background: 'url('+noiseFill(style.color, style.color2, style.intensity, style.opacity)+')'});
1007		} else
1008			debug('unimplemented fill:', style);
1009		return css;
1010	};
1011
1012
1013	$.fn.fillStyle = function (style) {
1014		util.fillStyleCss(style).forEach(this.css, this);
1015		return this;
1016	};
1017
1018	util.lineStyleCss = function (data) {
1019		if (!data) return [];
1020		var a = (typeof data == 'string') ? data.split(',') : data;
1021		var lineWidth = a[1];
1022		var lineColor = a[0];
1023		return [{border: 'solid ' + util.Color.toRgba(lineColor, true) + ' ' + Math.round(lineWidth) + 'px'}];
1024	};
1025
1026	util.cssFromList = function (list) {
1027		return list.map(function (css) {
1028			return Object.keys(css).map(function (name) {
1029				return '\t'+name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() + ': ' + css[name] + ';';
1030			}).join('\n');
1031		}).join('\n');
1032	};
1033
1034	$.fn.lineStyle = function (data) {
1035		util.lineStyleCss(data).forEach(this.css, this);
1036		return this;
1037	};
1038
1039	util.filterCss = function (filter, isText) {
1040		if (!filter) return [];
1041		return filter.map(function (param) {
1042
1043			if (param.type == 'dropShadow') {
1044				//debug(print_r($data,1));
1045				var ds = param.distance;
1046				var dx = Math.round(ds * Math.cos(param.angle / 180 * Math.PI));
1047				var dy = Math.round(ds * Math.sin(param.angle / 180 * Math.PI));
1048				var blur = param.blur;
1049
1050				var hex = Number(param.color).toString(16);
1051				if (param.strength) {
1052					if (isText) param.strength *= 0.6;
1053					hex = ('000000' + hex).slice(-6);
1054					hex = Math.round(param.strength * 255).toString(16) + hex;
1055				}
1056				var colorCss = util.Color.toRgba(hex);
1057
1058				var shadow = dx+'px '+dy+'px '+blur+'px '+colorCss;
1059				if (isText) return {textShadow: shadow};
1060				return {'-moz-box-shadow':shadow, '-webkit-box-shadow':shadow, boxShadow:shadow};
1061			}
1062
1063			if (param.type == 'glow') {
1064				var blur = param.x;
1065				var spread = param.x;
1066				var strength = param.strength/2;
1067				var color = util.Color.toRgba(Number(param.color).toString(16));
1068				var a = color.slice(5, -1).split(',');
1069				a[3] = strength;
1070				color = 'rgba(' + a.join(',') + ')';
1071
1072				var shadow = '0px 0px '+blur+'px '+spread+'px ' + color;
1073				return {'-moz-box-shadow':shadow, '-webkit-box-shadow':shadow, boxShadow:shadow};
1074			}
1075			debug('unknown filter: '+param.type);
1076			return {};
1077		});
1078	};
1079
1080	util.drawMenuButton = function ($cnv) {
1081		var sz = $cnv.width();
1082		var m = sz/4;
1083		var l = (sz - 2*m) / 5;
1084		var ctx = $cnv[0].getContext('2d');
1085		ctx.fillStyle = '#ffffff';
1086		ctx.rect(m, m, sz-2*m, l);
1087		ctx.rect(m, m+2*l, sz-2*m, l);
1088		ctx.rect(m, m+4*l, sz-2*m, l);
1089		ctx.fill();
1090	};
1091
1092	/* HTML building */
1093	var html = {
1094		img: function (src) { return $('<img/>').attr('src', src); },
1095		div: function (clazz) { return clazz ? $('<div/>').addClass(clazz) : $('<div/>'); },
1096		span: function (clazz) { return clazz ? $('<span/>').addClass(clazz) : $('<span/>'); },
1097		table: function () { return $('<table/>'); },
1098		tr: function () {return $('<tr/>'); },
1099		th: function () {return $('<th/>'); },
1100		td: function () {return $('<td/>'); },
1101		a: function () {return $('<a/>'); },
1102		input:  function (type) {return $('<input/>').attr('type', type?type:'text'); },
1103		mark: function() {return html.div().css({background:'red', width:10, height:10, position: 'absolute'});},
1104		vcenter: function ($content) {
1105			return html.table().height('100%').width('100%')
1106				.append(html.td().css('vertical-align','middle').append($content));
1107		},
1108		colorIcon: function () {return $('<div class="color-icon"><div></div></div>')},
1109		option: function (text, value) {
1110			var ret = $('<option/>').text(text);
1111			if (arguments.length == 2) ret.val(value);
1112			return ret;
1113		},
1114		loading: function () {return html.div('loading').css('display','inline-block')},
1115		iframe: function (src) { return $('<iframe/>').attr('src', src); }
1116	};
1117	util.html = html;
1118
1119	util.buildMobileNavBar = function (mobiNav, mobiFooter, navHeight, template, colors, titleCss, navCss) {
1120		var $titleBar = mobiNav.find('> .titleBar');
1121		$titleBar.attr('class').split(/\s+/).forEach(function (cls) {
1122			if (cls.substr(0, 8) == 'template') $titleBar.removeClass(cls);
1123		});
1124		$titleBar.css({
1125			height: navHeight
1126		}).find('.titleH').css(titleCss);
1127		$titleBar.addClass(template);
1128		var $paneTogg = mobiNav.find('> canvas').attr({width:navHeight, height:navHeight}).addClass('naviPaneTogg');
1129
1130		mobiNav.css({
1131			'background-color': util.Color.toRgba(colors.navigationBackground)
1132			//color: util.Color.toRgba(colors.navigationText)
1133		}).find('.item,a').css(navCss);
1134
1135		mobiFooter.css({
1136			padding: 10,
1137			'text-align': 'center',
1138			'background-color': util.Color.toRgba(colors.navigationBackground)
1139		});
1140
1141		mobiFooter.find('a').css({
1142			//color: util.Color.toRgba(colors.navigationText),
1143			'text-decoration': 'none'
1144		}).css(navCss);
1145
1146
1147		util.drawMenuButton($paneTogg);
1148	};
1149
1150	util.wrapElement = function ($el) {
1151		if (!$el.parent().is('.cb-effects')) {
1152			$el.wrap($('<div class="cb-effects"/>'));
1153			$el.parent().css('visibility', $el.css('visibility'));
1154			$el.css('visibility', '');
1155		}
1156	};
1157
1158	util.pickFile = function (hnd, multiple, images) {
1159		var $file = $('<input type="file">');
1160		if (images) $file.attr('accept', 'image/png, image/x-png, image/gif, image/jpeg');
1161		if (multiple) $file.attr('multiple', true);
1162		$file.on('change', function () {
1163			if (this.files.length == 0) return;
1164			hnd(multiple ? this.files : this.files[0]);
1165		});
1166		$file.trigger('click');
1167	}
1168})();
1169
1170//LINK ACTIONS
1171(function () {
1172
1173	//hide elements that will be shown by links
1174	$(function () {
1175		var prefix = 'javascript:CB5.action_showhide(';
1176		$('a[href]').each(function () {
1177			var href = $(this).attr('href');
1178			if (href.slice(0, prefix.length) === prefix) {
1179				var ids = JSON.parse(href.slice(prefix.length, -1)).show;
1180				ids.forEach(function (id) {
1181					getEl(id).css({visibility:'hidden'});
1182				});
1183			}
1184		});
1185	});
1186
1187	//Element Show/Hide
1188	CB5.action_showhide = function (o) {
1189		o.hide.forEach(function (id) {
1190			getEl(id).animate({opacity: 0});
1191		});
1192		o.show.forEach(function (id) {
1193			getEl(id).css({visibility:'visible', opacity:0}).animate({opacity:1});
1194		});
1195	}
1196
1197	function getEl(id, b) {
1198		var $el = $('#'+id);
1199		if ($el.parent().is('.cb-effects'))
1200			$el = $el.parent();
1201		return $el;
1202	}
1203
1204
1205	//Show mobile
1206	CB5.action_mobile = function () {
1207		top.location = '?full=0&mobile=1';
1208	};
1209	//submit form
1210	CB5.action_submit = function () {
1211		$('.cb-form').last().submit();
1212	};
1213
1214	CB5.action_scroll = function (id) {
1215		$('#'+id+',#m_'+id).scrollintoview();
1216		history.pushState(null, '', '#'+id);
1217	}
1218
1219})();
1220
1221//Image effects: reflection, ...
1222(function () {
1223	var util = CB5.util;
1224
1225	//Effects, now with Pixastic
1226	util.Filter = {
1227		'do': function (canvas, action, options) {
1228			if (action == 'blur' && typeof blurCanvas != 'undefined') {
1229				blurCanvas(canvas, options.amount);
1230				return;
1231			}
1232
1233			options.resultCanvas = canvas;
1234			options.leaveDOM = true;
1235			if (typeof Pixastic != 'undefined')
1236				Pixastic.process(canvas, action, options);
1237		}
1238	};
1239
1240	CB5.ImageEffects = {
1241		//TODO separate reflection from filters
1242		render: function ($img, matrix, filterData, reflectionData) {
1243			var $cnv;
1244			var filters = [];
1245			if (filterData) {
1246				filterData.split(',').forEach(function (str) {
1247					var p = util.parseParams(str);
1248					if (p.type == 'dropShadow' || p.type == 'glow') return;
1249					filters.push(p);
1250				}, this);
1251			}
1252
1253			if (!filters.length && !reflectionData) return;
1254			$img.wrap('<div class="cb-effects"/>');
1255
1256			if (reflectionData) {
1257				var p = util.parseParams(reflectionData);
1258				$cnv = $('<canvas style="position:absolute"/>');
1259				var b = $img[0].getBoundingClientRect();
1260				var m = matrix.clone();
1261				m.ty += b.height + b.height * p.y / 100;
1262				$cnv.matrix(m);
1263
1264				$img.before($cnv);
1265				this._reflection($img[0], $cnv, p);
1266			}
1267			if (filters.length) {
1268				$cnv = $('<canvas style="position:absolute"/>')
1269					.attr({width: $img[0].naturalWidth, height: $img[0].naturalHeight});
1270				$cnv.matrix(matrix);
1271				$img.before($cnv);
1272				$img.css({opacity: 0});
1273
1274				filters.forEach(function (p) {
1275					if (!this.hasOwnProperty('_' + p.type)) {
1276						sb.debug('no such filter: ' + p.type, $img[0]);
1277						return;
1278					}
1279					this['_' + p.type]($img, $cnv, p);
1280				}, this);
1281			}
1282		},
1283
1284        addTint: function($img, matrix, tintData, elId) {
1285            if (!tintData) return;
1286            var $cnv = $('<canvas style="position:absolute;z-index: 100"/>').addClass('cbel cb-tint');
1287            if(elId) {
1288                $('.colorTint-'+elId).remove();
1289                $cnv.addClass('colorTint-'+elId);
1290            }
1291            var m = matrix.clone();
1292            $img.before($cnv);
1293            $cnv.matrix(m);
1294            var w = $img[0].naturalWidth, h = $img[0].naturalHeight;
1295            $cnv.attr({width: w, height: h});
1296            var ctx = $cnv[0].getContext('2d');
1297            ctx.fillStyle = ''+tintData;
1298            ctx.fillRect(0, 0 , w, h);
1299        },
1300
1301		_blur: function ($img, $cnv, p) {
1302			var ctx = $cnv[0].getContext('2d');
1303			ctx.drawImage($img[0], 0, 0);
1304			util.Filter.do($cnv[0], 'blur', {amount: p.x});
1305		},
1306
1307		_sharpen: function ($img, $cnv, p) {
1308			var ctx = $cnv[0].getContext('2d');
1309			ctx.drawImage($img[0], 0, 0);
1310			util.Filter.do($cnv[0], 'sharpen', {amount: p.multiply / 100});
1311		},
1312
1313		_colorMatrix: function ($img, $cnv, p) {
1314			var ctx = $cnv[0].getContext('2d');
1315			ctx.drawImage($img[0], 0, 0);
1316			if (p.hue != 0 || p.saturation != 0)
1317				util.Filter.do($cnv[0], 'hsl', {hue: p.hue, saturation: p.saturation});
1318			if (p.contrast != 0 || p.brightness != 0)
1319				util.Filter.do($cnv[0], 'brightness', {brightness: p.brightness, contrast: p.contrast / 100})
1320		},
1321
1322		_emboss: function ($img, $cnv, p) {
1323			var ctx = $cnv[0].getContext('2d');
1324			ctx.drawImage($img[0], 0, 0);
1325			util.Filter.do($cnv[0], 'emboss', {strength: p.multiply / 100 * 2, blend: true, greyLevel: 0})
1326		},
1327
1328		_reflection: function (img, $cnv, p) {
1329
1330			var w = img.naturalWidth, h = img.naturalHeight;
1331			$cnv.attr({width: w, height: h});
1332
1333			//sb.debug(p)
1334			var ctx = $cnv[0].getContext('2d');
1335
1336			var g = ctx.createLinearGradient(0, 0, 0, h);
1337			[[0, 1], [0.2, 0.3], [0.3, 0.2], [1, 0]].forEach(function (a) {
1338				//var alpha = Math.pow(a[1],1-Math.pow(p.strength,4));
1339				var alpha = a[1] * p.strength + Math.pow(p.strength, 6);
1340				//sb.debug(alpha, a[1]*p.strength, Math.pow(p.strength,6))
1341				g.addColorStop(a[0], 'rgba(0,0,0,' + alpha + ')');
1342			});
1343			ctx.fillStyle = g;
1344			ctx.fillRect(0, 0, w, h);
1345
1346			ctx.globalCompositeOperation = 'source-in';
1347			ctx.save();
1348			ctx.transform(1, 0, 0, -1, 0, h);
1349			ctx.drawImage(img, 0, 0);
1350			ctx.restore();
1351
1352			//blurCanvas($reflection[0], p.blur);
1353			util.Filter.do($cnv[0], 'blur', {amount: p.blur});
1354		}
1355	};
1356	
1357	$.fn.isInViewport = function () {
1358		var el = this[0], s = false;
1359		if (!el) return;
1360		if (this.css('display') == 'none') {
1361			this.css({display: 'block', visibility:'hidden'});
1362			s = true;
1363		}
1364		var rect = el.getBoundingClientRect();
1365		if (s) this.css({display: 'none', visibility:'visible'});
1366		return rect.top < $(window).height() && rect.left < $(window).width();
1367	}
1368})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.