PageSourceSearch

https://i-sosna.ru/bitrix/templates/adaptive/js/jcf.js?178544501624609

js i-sosna.ru collected 2026-10-04 16:08:10 UTC 24,609 bytes, 735 lines download raw bytes

1/*
2 * JavaScript Custom Forms Module
3 */
4jcf = {
5	// global options
6	modules: {},
7	plugins: {},
8	baseOptions: {
9		unselectableClass:'jcf-unselectable',
10		labelActiveClass:'jcf-label-active',
11		labelDisabledClass:'jcf-label-disabled',
12		classPrefix: 'jcf-class-',
13		hiddenClass:'jcf-hidden',
14		focusClass:'jcf-focus',
15		wrapperTag: 'div'
16	},
17	// replacer function
18	customForms: {
19		setOptions: function(obj) {
20			for(var p in obj) {
21				if(obj.hasOwnProperty(p) && typeof obj[p] === 'object') {
22					jcf.lib.extend(jcf.modules[p].prototype.defaultOptions, obj[p]);
23				}
24			}
25		},
26		replaceAll: function(context) {
27			for(var k in jcf.modules) {
28				var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector, context);
29				for(var i = 0; i<els.length; i++) {
30					if(els[i].jcf) {
31						// refresh form element state
32						els[i].jcf.refreshState();
33					} else {
34						// replace form element
35						if(!jcf.lib.hasClass(els[i], 'default') && jcf.modules[k].prototype.checkElement(els[i])) {
36							new jcf.modules[k]({
37								replaces:els[i]
38							});
39						}
40					}
41				}
42			}
43		},
44		refreshAll: function(context) {
45			for(var k in jcf.modules) {
46				var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector, context);
47				for(var i = 0; i<els.length; i++) {
48					if(els[i].jcf) {
49						// refresh form element state
50						els[i].jcf.refreshState();
51					}
52				}
53			}
54		},
55		refreshElement: function(obj) {
56			if(obj && obj.jcf) {
57				obj.jcf.refreshState();
58			}
59		},
60		destroyAll: function() {
61			for(var k in jcf.modules) {
62				var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector);
63				for(var i = 0; i<els.length; i++) {
64					if(els[i].jcf) {
65						els[i].jcf.destroy();
66					}
67				}
68			}
69		}
70	},
71	// detect device type
72	isTouchDevice: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
73	isWinPhoneDevice: navigator.msPointerEnabled && /MSIE 10.*Touch/.test(navigator.userAgent),
74	// define base module
75	setBaseModule: function(obj) {
76		jcf.customControl = function(opt){
77			this.options = jcf.lib.extend({}, jcf.baseOptions, this.defaultOptions, opt);
78			this.init();
79		};
80		for(var p in obj) {
81			jcf.customControl.prototype[p] = obj[p];
82		}
83	},
84	// add module to jcf.modules
85	addModule: function(obj) {
86		if(obj.name){
87			// create new module proto class
88			jcf.modules[obj.name] = function(){
89				jcf.modules[obj.name].superclass.constructor.apply(this, arguments);
90			}
91			jcf.lib.inherit(jcf.modules[obj.name], jcf.customControl);
92			for(var p in obj) {
93				jcf.modules[obj.name].prototype[p] = obj[p]
94			}
95			// on create module
96			jcf.modules[obj.name].prototype.onCreateModule();
97			// make callback for exciting modules
98			for(var mod in jcf.modules) {
99				if(jcf.modules[mod] != jcf.modules[obj.name]) {
100					jcf.modules[mod].prototype.onModuleAdded(jcf.modules[obj.name]);
101				}
102			}
103		}
104	},
105	// add plugin to jcf.plugins
106	addPlugin: function(obj) {
107		if(obj && obj.name) {
108			jcf.plugins[obj.name] = function() {
109				this.init.apply(this, arguments);
110			}
111			for(var p in obj) {
112				jcf.plugins[obj.name].prototype[p] = obj[p];
113			}
114		}
115	},
116	// miscellaneous init
117	init: function(){
118		if(navigator.pointerEnabled) {
119			this.eventPress = 'pointerdown';
120			this.eventMove = 'pointermove';
121			this.eventRelease = 'pointerup';
122		} else if(navigator.msPointerEnabled) {
123			this.eventPress = 'MSPointerDown';
124			this.eventMove = 'MSPointerMove';
125			this.eventRelease = 'MSPointerUp';
126		} else {
127			this.eventPress = this.isTouchDevice ? 'touchstart' : 'mousedown';
128			this.eventMove = this.isTouchDevice ? 'touchmove' : 'mousemove';
129			this.eventRelease = this.isTouchDevice ? 'touchend' : 'mouseup';
130		}
131
132		setTimeout(function(){
133			jcf.lib.domReady(function(){
134				jcf.initStyles();
135			});
136		},1);
137		return this;
138	},
139	initStyles: function() {
140		// create <style> element and rules
141		var head = document.getElementsByTagName('head')[0],
142			style = document.createElement('style'),
143			rules = document.createTextNode('.'+jcf.baseOptions.unselectableClass+'{'+
144				'-moz-user-select:none;'+
145				'-webkit-tap-highlight-color:rgba(255,255,255,0);'+
146				'-webkit-user-select:none;'+
147				'user-select:none;'+
148			'}');
149
150		// append style element
151		style.type = 'text/css';
152		if(style.styleSheet) {
153			style.styleSheet.cssText = rules.nodeValue;
154		} else {
155			style.appendChild(rules);
156		}
157		head.appendChild(style);
158	}
159}.init();
160
161/*
162 * Custom Form Control prototype
163 */
164jcf.setBaseModule({
165	init: function(){
166		if(this.options.replaces) {
167			this.realElement = this.options.replaces;
168			this.realElement.jcf = this;
169			this.replaceObject();
170		}
171	},
172	defaultOptions: {
173		// default module options (will be merged with base options)
174	},
175	checkElement: function(el){
176		return true;
176 // additional check for correct form element
177	},
178	replaceObject: function(){
179		this.createWrapper();
180		this.attachEvents();
181		this.fixStyles();
182		this.setupWrapper();
183	},
184	createWrapper: function(){
185		this.fakeElement = jcf.lib.createElement(this.options.wrapperTag);
186		this.labelFor = jcf.lib.getLabelFor(this.realElement);
187		jcf.lib.disableTextSelection(this.fakeElement);
188		jcf.lib.addClass(this.fakeElement, jcf.lib.getAllClasses(this.realElement.className, this.options.classPrefix));
189		jcf.lib.addClass(this.realElement, jcf.baseOptions.hiddenClass);
190	},
191	attachEvents: function(){
192		jcf.lib.event.add(this.realElement, 'focus', this.onFocusHandler, this);
193		jcf.lib.event.add(this.realElement, 'blur', this.onBlurHandler, this);
194		jcf.lib.event.add(this.fakeElement, 'click', this.onFakeClick, this);
195		jcf.lib.event.add(this.fakeElement, jcf.eventPress, this.onFakePressed, this);
196		jcf.lib.event.add(this.fakeElement, jcf.eventRelease, this.onFakeReleased, this);
197
198		if(this.labelFor) {
199			this.labelFor.jcf = this;
200			jcf.lib.event.add(this.labelFor, 'click', this.onFakeClick, this);
201			jcf.lib.event.add(this.labelFor, jcf.eventPress, this.onFakePressed, this);
202			jcf.lib.event.add(this.labelFor, jcf.eventRelease, this.onFakeReleased, this);
203		}
204	},
205	fixStyles: function() {
206		// hide mobile webkit tap effect
207		if(jcf.isTouchDevice) {
208			var tapStyle = 'rgba(255,255,255,0)';
209			this.realElement.style.webkitTapHighlightColor = tapStyle;
210			this.fakeElement.style.webkitTapHighlightColor = tapStyle;
211			if(this.labelFor) {
212				this.labelFor.style.webkitTapHighlightColor = tapStyle;
213			}
214		}
215	},
216	setupWrapper: function(){
217		// implement in subclass
218	},
219	refreshState: function(){
220		// implement in subclass
221	},
222	destroy: function() {
223		if(this.fakeElement && this.fakeElement.parentNode) {
224			this.fakeElement.parentNode.insertBefore(this.realElement, this.fakeElement);
225			this.fakeElement.parentNode.removeChild(this.fakeElement);
226		}
227		jcf.lib.removeClass(this.realElement, jcf.baseOptions.hiddenClass);
228		this.realElement.jcf = null;
229	},
230	onFocus: function(){
231		// emulated focus event
232		jcf.lib.addClass(this.fakeElement,this.options.focusClass);
233	},
234	onBlur: function(cb){
235		// emulated blur event
236		jcf.lib.removeClass(this.fakeElement,this.options.focusClass);
237	},
238	onFocusHandler: function() {
239		// handle focus loses
240		if(this.focused) return;
241		this.focused = true;
242
243		// handle touch devices also
244		if(jcf.isTouchDevice) {
245			if(jcf.focusedInstance && jcf.focusedInstance.realElement != this.realElement) {
246				jcf.focusedInstance.onBlur();
247				jcf.focusedInstance.realElement.blur();
248			}
249			jcf.focusedInstance = this;
250		}
251		this.onFocus.apply(this, arguments);
252	},
253	onBlurHandler: function() {
254		// handle focus loses
255		if(!this.pressedFlag) {
256			this.focused = false;
257			this.onBlur.apply(this, arguments);
258		}
259	},
260	onFakeClick: function(){
261		if(jcf.isTouchDevice) {
262			this.onFocus();
263		} else if(!this.realElement.disabled) {
264			this.realElement.focus();
265		}
266	},
267	onFakePressed: function(e){
268		this.pressedFlag = true;
269	},
270	onFakeReleased: function(){
271		this.pressedFlag = false;
272	},
273	onCreateModule: function(){
274		// implement in subclass
275	},
276	onModuleAdded: function(module) {
277		// implement in subclass
278	},
279	onControlReady: function() {
280		// implement in subclass
281	}
282});
283
284/*
285 * JCF Utility Library
286 */
287jcf.lib = {
288	bind: function(func, scope){
289		return function() {
290			return func.apply(scope, arguments);
291		};
292	},
293	browser: (function() {
294		var ua = navigator.userAgent.toLowerCase(), res = {},
295		match = /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version)?[ \/]([\w.]+)/.exec(ua) ||
296				/(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+))?/.exec(ua) || [];
297		res[match[1]] = true;
298		res.version = match[2] || "0";
299		res.safariMac = ua.indexOf('mac') != -1 && ua.indexOf('safari') != -1;
300		return res;
301	})(),
302	getOffset: function (obj) {
303		if (obj.getBoundingClientRect && !jcf.isWinPhoneDevice) {
304			var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
305			var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
306			var clientLeft = document.documentElement.clientLeft || document.body.clientLeft || 0;
307			var clientTop = document.documentElement.clientTop || document.body.clientTop || 0;
308			return {
309				top:Math.round(obj.getBoundingClientRect().top + scrollTop - clientTop),
310				left:Math.round(obj.getBoundingClientRect().left + scrollLeft - clientLeft)
311			};
312		} else {
313			var posLeft = 0, posTop = 0;
314			while (obj.offsetParent) {posLeft += obj.offsetLeft; posTop += obj.offsetTop; obj = obj.offsetParent;}
315			return {top:posTop,left:posLeft};
316		}
317	},
318	getScrollTop: function() {
319		return window.pageYOffset || document.documentElement.scrollTop;
320	},
321	getScrollLeft: function() {
322		return window.pageXOffset || document.documentElement.scrollLeft;
323	},
324	getWindowWidth: function(){
325		return document.compatMode=='CSS1Compat' ? document.documentElement.clientWidth : document.body.clientWidth;
326	},
327	getWindowHeight: function(){
328		return document.compatMode=='CSS1Compat' ? document.documentElement.clientHeight : document.body.clientHeight;
329	},
330	getStyle: function(el, prop) {
331		if (document.defaultView && document.defaultView.getComputedStyle) {
332			return document.defaultView.getComputedStyle(el, null)[prop];
333		} else if (el.currentStyle) {
334			return el.currentStyle[prop];
335		} else {
336			return el.style[prop];
337		}
338	},
339	getParent: function(obj, selector) {
340		while(obj.parentNode && obj.parentNode != document.body) {
341			if(obj.parentNode.tagName.toLowerCase() == selector.toLowerCase()) {
342				return obj.parentNode;
343			}
344			obj = obj.parentNode;
345		}
346		return false;
347	},
348	isParent: function(parent, child) {
349		while(child.parentNode) {
350			if(child.parentNode === parent) {
351				return true;
352			}
353			child = child.parentNode;
354		}
355		return false;
356	},
357	getLabelFor: function(object) {
358		var parentLabel = jcf.lib.getParent(object,'label');
359		if(parentLabel) {
360			return parentLabel;
361		} else if(object.id) {
362			return jcf.lib.queryBySelector('label[for="' + object.id + '"]')[0];
363		}
364	},
365	disableTextSelection: function(el){
366		if (typeof el.onselectstart !== 'undefined') {
367			el.onselectstart = function() {return false;};
368		} else if(window.opera) {
369			el.setAttribute('unselectable', 'on');
370		} else {
371			jcf.lib.addClass(el, jcf.baseOptions.unselectableClass);
372		}
373	},
374	enableTextSelection: function(el) {
375		if (typeof el.onselectstart !== 'undefined') {
376			el.onselectstart = null;
377		} else if(window.opera) {
378			el.removeAttribute('unselectable');
379		} else {
380			jcf.lib.removeClass(el, jcf.baseOptions.unselectableClass);
381		}
382	},
383	queryBySelector: function(selector, scope){
384		if(typeof scope === 'string') {
385			var result = [];
386			var holders = this.getElementsBySelector(scope);
387			for (var i = 0, contextNodes; i < holders.length; i++) {
388				contextNodes = Array.prototype.slice.call(this.getElementsBySelector(selector, holders[i]));
389				result = result.concat(contextNodes);
390			}
391			return result;
392		} else {
393			return this.getElementsBySelector(selector, scope);
394		}
395	},
396	prevSibling: function(node) {
397		while(node = node.previousSibling) if(node.nodeType == 1) break;
398		return node;
399	},
400	nextSibling: function(node) {
401		while(node = node.nextSibling) if(node.nodeType == 1) break;
402		return node;
403	},
404	fireEvent: function(element,event) {
405		if(element.dispatchEvent){
406			var evt = document.createEvent('HTMLEvents');
407			evt.initEvent(event, true, true );
408			return !element.dispatchEvent(evt);
409		}else if(document.createEventObject){
410			var evt = document.createEventObject();
411			return element.fireEvent('on'+event,evt);
412		}
413	},
414	inherit: function(Child, Parent) {
415		var F = function() { }
416		F.prototype = Parent.prototype
417		Child.prototype = new F()
418		Child.prototype.constructor = Child
419		Child.superclass = Parent.prototype
420	},
421	extend: function(obj) {
422		for(var i = 1; i < arguments.length; i++) {
423			for(var p in arguments[i]) {
424				if(arguments[i].hasOwnProperty(p)) {
425					obj[p] = arguments[i][p];
426				}
427			}
428		}
429		return obj;
430	},
431	hasClass: function (obj,cname) {
432		return (obj.className ? obj.className.match(new RegExp('(\\s|^)'+cname+'(\\s|$)')) : false);
433	},
434	addClass: function (obj,cname) {
435		if (!this.hasClass(obj,cname)) obj.className += (!obj.className.length || obj.className.charAt(obj.className.length - 1) === ' ' ? '' : ' ') + cname;
436	},
437	removeClass: function (obj,cname) {
438		if (this.hasClass(obj,cname)) obj.className=obj.className.replace(new RegExp('(\\s|^)'+cname+'(\\s|$)'),' ').replace(/\s+$/, '');
439	},
440	toggleClass: function(obj, cname, condition) {
441		if(condition) this.addClass(obj, cname); else this.removeClass(obj, cname);
442	},
443	createElement: function(tagName, options) {
444		var el = document.createElement(tagName);
445		for(var p in options) {
446			if(options.hasOwnProperty(p)) {
447				switch (p) {
448					case 'class': el.className = options[p]; break;
449					case 'html': el.innerHTML = options[p]; break;
450					case 'style': this.setStyles(el, options[p]); break;
451					default: el.setAttribute(p, options[p]);
452				}
453			}
454		}
455		return el;
456	},
457	setStyles: function(el, styles) {
458		for(var p in styles) {
459			if(styles.hasOwnProperty(p)) {
460				switch (p) {
461					case 'float': el.style.cssFloat = styles[p]; break;
462					case 'opacity': el.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+styles[p]*100+')'; el.style.opacity = styles[p]; break;
463					default: el.style[p] = (typeof styles[p] === 'undefined' ? 0 : styles[p]) + (typeof styles[p] === 'number' ? 'px' : '');
464				}
465			}
466		}
467		return el;
468	},
469	getInnerWidth: function(el) {
470		return el.offsetWidth - (parseInt(this.getStyle(el,'paddingLeft')) || 0) - (parseInt(this.getStyle(el,'paddingRight')) || 0);
471	},
472	getInnerHeight: function(el) {
473		return el.offsetHeight - (parseInt(this.getStyle(el,'paddingTop')) || 0) - (parseInt(this.getStyle(el,'paddingBottom')) || 0);
474	},
475	getAllClasses: function(cname, prefix, skip) {
476		if(!skip) skip = '';
477		if(!prefix) prefix = '';
478		return cname ? cname.replace(new RegExp('(\\s|^)'+skip+'(\\s|$)'),' ').replace(/[\s]*([\S]+)+[\s]*/gi,prefix+"$1 ") : '';
479	},
480	getElementsBySelector: function(selector, scope) {
481		if(typeof document.querySelectorAll === 'function') {
482			return (scope || document).querySelectorAll(selector);
483		}
484		var selectors = selector.split(',');
485		var resultList = [];
486		for(var s = 0; s < selectors.length; s++) {
487			var currentContext = [scope || document];
488			var tokens = selectors[s].replace(/^\s+/,'').replace(/\s+$/,'').split(' ');
489			for (var i = 0; i < tokens.length; i++) {
490				token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');
491				if (token.indexOf('#') > -1) {
492					var bits = token.split('#'), tagName = bits[0], id = bits[1];
493					var element = document.getElementById(id);
494					if (tagName && element.nodeName.toLowerCase() != tagName) {
495						return [];
496					}
497					currentContext = [element];
498					continue;
499				}
500				if (token.indexOf('.') > -1) {
501					var bits = token.split('.'), tagName = bits[0] || '*', className = bits[1], found = [], foundCount = 0;
502					for (var h = 0; h < currentContext.length; h++) {
503						var elements;
504						if (tagName == '*') {
505							elements = currentContext[h].getElementsByTagName('*');
506						} else {
507							elements = currentContext[h].getElementsByTagName(tagName);
508						}
509						for (var j = 0; j < elements.length; j++) {
510							found[foundCount++] = elements[j];
511						}
512					}
513					currentContext = [];
514					var currentContextIndex = 0;
515					for (var k = 0; k < found.length; k++) {
516						if (found[k].className && found[k].className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'))) {
517							currentContext[currentContextIndex++] = found[k];
518						}
519					}
520					continue;
521				}
522				if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
523					var tagName = RegExp.$1 || '*', attrName = RegExp.$2, attrOperator = RegExp.$3, attrValue = RegExp.$4;
524					if(attrName.toLowerCase() == 'for' && this.browser.msie && this.browser.version < 8) {
525						attrName = 'htmlFor';
526					}
527					var found = [], foundCount = 0;
528					for (var h = 0; h < currentContext.length; h++) {
529						var elements;
530						if (tagName == '*') {
531							elements = currentContext[h].getElementsByTagName('*');
532						} else {
533							elements = currentContext[h].getElementsByTagName(tagName);
534						}
535						for (var j = 0; elements[j]; j++) {
536							found[foundCount++] = elements[j];
537						}
538					}
539					currentContext = [];
540					var currentContextIndex = 0, checkFunction;
541					switch (attrOperator) {
542						case '=': checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue) }; break;
543						case '~': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('(\\s|^)'+attrValue+'(\\s|$)'))) }; break;
544						case '|': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))) }; break;
545						case '^': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0) }; break;
546						case '$': checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length) }; break;
547						case '*': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1) }; break;
548						default : checkFunction = function(e) { return e.getAttribute(attrName) };
549					}
550					currentContext = [];
551					var currentContextIndex = 0;
552					for (var k = 0; k < found.length; k++) {
553						if (checkFunction(found[k])) {
554							currentContext[currentContextIndex++] = found[k];
555						}
556					}
557					continue;
558				}
559				tagName = token;
560				var found = [], foundCount = 0;
561				for (var h = 0; h < currentContext.length; h++) {
562					var elements = currentContext[h].getElementsByTagName(tagName);
563					for (var j = 0; j < elements.length; j++) {
564						found[foundCount++] = elements[j];
565					}
566				}
567				currentContext = found;
568			}
569			resultList = [].concat(resultList,currentContext);
570		}
571		return resultList;
572	},
573	scrollSize: (function(){
574		var content, hold, sizeBefore, sizeAfter;
575		function buildSizer(){
576			if(hold) removeSizer();
577			content = document.createElement('div');
578			hold = document.createElement('div');
579			hold.style.cssText = 'position:absolute;overflow:hidden;width:100px;height:100px';
580			hold.appendChild(content);
581			document.body.appendChild(hold);
582		}
583		function removeSizer(){
584			document.body.removeChild(hold);
585			hold = null;
586		}
587		function calcSize(vertical) {
588			buildSizer();
589			content.style.cssText = 'height:'+(vertical ? '100%' : '200px');
590			sizeBefore = (vertical ? content.offsetHeight : content.offsetWidth);
591			hold.style.overflow = 'scroll'; content.innerHTML = 1;
592			sizeAfter = (vertical ? content.offsetHeight : content.offsetWidth);
593			if(vertical && hold.clientHeight) sizeAfter = hold.clientHeight;
594			removeSizer();
595			return sizeBefore - sizeAfter;
596		}
597		return {
598			getWidth:function(){
599				return calcSize(false);
600			},
601			getHeight:function(){
602				return calcSize(true)
603			}
604		}
605	}()),
606	domReady: function (handler){
607		var called = false
608		function ready() {
609			if (called) return;
610			called = true;
611			handler();
612		}
613		if (document.addEventListener) {
614			document.addEventListener("DOMContentLoaded", ready, false);
615		} else if (document.attachEvent) {
616			if (document.documentElement.doScroll && window == window.top) {
617				function tryScroll(){
618					if (called) return
619					if (!document.body) return
620					try {
621						document.documentElement.doScroll("left")
622						ready()
623					} catch(e) {
624						setTimeout(tryScroll, 0)
625					}
626				}
627				tryScroll()
628			}
629			document.attachEvent("onreadystatechange", function(){
630				if (document.readyState === "complete") {
631					ready()
632				}
633			})
634		}
635		if (window.addEventListener) window.addEventListener('load', ready, false)
636		else if (window.attachEvent) window.attachEvent('onload', ready)
637	},
638	event: (function(){
639		var guid = 0;
640		function fixEvent(e) {
641			e = e || window.event;
642			if (e.isFixed) {
643				return e;
644			}
645			e.isFixed = true; 
646			e.preventDefault = e.preventDefault || function(){this.returnValue = false}
647			e.stopPropagation = e.stopPropagation || function(){this.cancelBubble = true}
648			if (!e.target) {
649				e.target = e.srcElement
650			}
651			if (!e.relatedTarget && e.fromElement) {
652				e.relatedTarget = e.fromElement == e.target ? e.toElement : e.fromElement;
653			}
654			if (e.pageX == null && e.clientX != null) {
655				var html = document.documentElement, body = document.body;
656				e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
657				e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
658			}
659			if (!e.which && e.button) {
660				e.which = e.button & 1 ? 1 : (e.button & 2 ? 3 : (e.button & 4 ? 2 : 0));
661			}
662			if(e.type === "DOMMouseScroll" || e.type === 'mousewheel') {
663				e.mWheelDelta = 0;
664				if (e.wheelDelta) {
665					e.mWheelDelta = e.wheelDelta/120;
666				} else if (e.detail) {
667					e.mWheelDelta = -e.detail/3;
668				}
669			}
670			return e;
671		}
672		function commonHandle(event, customScope) {
673			event = fixEvent(event);
674			var handlers = this.events[event.type];
675			for (var g in handlers) {
676				var handler = handlers[g];
677				var ret = handler.call(customScope || this, event);
678				if (ret === false) {
679					event.preventDefault()
680					event.stopPropagation()
681				}
682			}
683		}
684		var publicAPI = {
685			add: function(elem, type, handler, forcedScope) {
686				if (elem.setInterval && (elem != window && !elem.frameElement)) {
687					elem = window;
688				}
689				if (!handler.guid) {
690					handler.guid = ++guid;
691				}
692				if (!elem.events) {
693					elem.events = {};
694					elem.handle = function(event) {
695						return commonHandle.call(elem, event);
696					}
697				}
698				if (!elem.events[type]) {
699					elem.events[type] = {};
700					if (elem.addEventListener) elem.addEventListener(type, elem.handle, false);
701					else if (elem.attachEvent) elem.attachEvent("on" + type, elem.handle);
702					if(type === 'mousewheel') {
703						publicAPI.add(elem, 'DOMMouseScroll', handler, forcedScope);
704					}
705				}
706				var fakeHandler = jcf.lib.bind(handler, forcedScope);
707				fakeHandler.guid = handler.guid;
708				elem.events[type][handler.guid] = forcedScope ? fakeHandler : handler;
709			},
710			remove: function(elem, type, handler) {
711				var handlers = elem.events && elem.events[type];
712				if (!handlers) return;
713				delete handlers[handler.guid];
714				for(var any in handlers) return;
715				if (elem.removeEventListener) elem.removeEventListener(type, elem.handle, false);
716				else if (elem.detachEvent) elem.detachEvent("on" + type, elem.handle);
717				delete elem.events[type];
718				for (var any in elem.events) return;
719				try {
720					delete elem.handle;
721					delete elem.events;
722				} catch(e) {
723					if(elem.removeAttribute) {
724						elem.removeAttribute("handle");
725						elem.removeAttribute("events");
726					}
727				}
728				if(type === 'mousewheel') {
729					publicAPI.remove(elem, 'DOMMouseScroll', handler);
730				}
731			}
732		}
733		return publicAPI;
734	}())
735}

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.