PageSourceSearch

https://maestrocares.org/cms3t/res/vit-lib/common.js

js maestrocares.org collected 2026-10-01 14:42:03 UTC 95,519 bytes, 3,353 lines download raw bytes

1/**********************************************************************************\
2 * Set of common java helpers.
3 *
4 * The MIT License
5 *
6 * Copyright (c) 2008 Victor Denisenkov aka Mr.V!T
7 *
8 * Permission  is hereby granted, free of charge, to any person obtaining a copy of
9 * this  software  and  associated documentation files (the "Software"), to deal in
10 * the  Software  without  restriction,  including without limitation the rights to
11 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 * the  Software, and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
14 *
15 * The  above  copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 * FOR  A  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 * COPYRIGHT  HOLDERS  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 * IN  AN  ACTION  OF  CONTRACT,  TORT  OR  OTHERWISE,  ARISING  FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * @package vit-lib
26 * @author Victor Denisenkov aka Mr.V!T
27 * @version 1.0
28\**********************************************************************************/
29
30/** //** ----= escapeHtmlTags	 =----------------------------------------------\**//** \
31*
32* 	Converts common HTML chars into entities.
33*
34*	@param	string	str	- HTML code to convert.
35*	@return	string		- Escaped HTML.
36*
37\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
38var escapeHtmlTags_chars = {
39	'&'	: '&',
40	'<'	: '&lt;',
41	'>'	: '&gt;',
42	'"'	: '&quot;',
43	"'"	: '&#039;'
44} //OBJECT escapeHtmlTags_chars
45function escapeHtmlTags(str) {
46
47	//If smth wrong given, just returning it back
48	if ( typeof(str) !== 'string' ) return str;
49
50	return str.replace(/['"&<>]/g, function (c) {
51		return escapeHtmlTags_chars[c] || c;
52	}); //FUNC string.replace.callback
53} //FUNC escapeHtmlTags
54
55function decodeEntities ($str) {
56
57	for ( var $i in escapeHtmlTags_chars )
58		$str = $str.replace(escapeHtmlTags_chars[$i], $i);
59
60	return $str;
61} //FUNC decodeEntities
62
63function getUrlHash () {
64	return location.hash.replace(/^#/, '');
65} //FUNC getUrlHash
66
67/** //** ----= fullURL	=----------------------------------------------------------------------------------------------\**//** \
68*
69*	Takes any URL and makes it full URL adding host if necesarry.
70* 	Uses window.location for host value and autodetected scheme.
71*
72*	@param		string	$url		- Url to check.
73* 	@param		bool	[$https]	- Create https url.
74*
75*	@return		string			- Full URL
76*
77\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
78function fullURL ($url, $https) {
79
80	// Preparing desired shceme
81	if ( isUndefined($https) )
82		$scheme = window.location.protocol+'//';
83	else
84		$scheme = ($https) ? 'https://' : 'http://' ;
85
86	// Checking for sceme on string begining
87	if ( $url.indexOf($scheme) !== 0 )
88		$url = $scheme+window.location.host+'/'+$url.ltrim(' \/');
89
90	return $url;
91} //FUNC fullURL
92
93/** //** ----= regexMatchAll	=----------------------------------------------------------------------------------------------\**//** \
94*
95*	Executes regex on string multiple times, untill no further matches found. Returns array of matches.
96*	Supports PREG_SET_ORDER and PREG_PATTERN_ORDER similar to php's preg_match_all.
97*
98*	@param		string	$str		- String to match.
99* 	@param		regex	$regex		- Regular expression.
100*
101*	@return		array			- All matches as array.
102*
103\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
104var PREG_PATTERN_ORDER	= 1;
105var PREG_SET_ORDER	= 2;
106function regexMatchAll ($regex, $str, $order) {
107
108	// Order by default is PREG_PATTERN_ORDER to mimic php
109	$order = $order || PREG_PATTERN_ORDER;
110
111	var $match;
112	var $res = [];
113
114	// Looping through results
115	// This will create results as for PREG_SET_ORDER flag
116	while ( $match = $regex.exec($str) ) {
117
118		// Removing some trash, to end up with true array
119		// It's important to allow [for var in array] code.
120		delete($match['index']);
121		delete($match['input']);
122
123		$res.push($match);
124	} //WHILE matching
125
126	// Done if no need to reorder
127	if ( $order === PREG_SET_ORDER )
128		return $res;
129
130	// Reordering in new array if necessary
131	var $tmp = [];
132	for ( var $i in $res )
133		for ( var $j in $res[$i] )
134			// Pushing matches if subset exists, or creating new one if not
135			$tmp[$j] ? $tmp[$j].push($res[$i][$j]) : $tmp[$j] = [$res[$i][$j]];
136
137	return $tmp;
138} //FUNC regexMatchAll
139
140if ( isUndefined( jQuery.fn.disableSelection ) ) {
141
142jQuery.fn.disableSelection = function() {
143	// Preparing event name, to allow selectstart or fallback to mousedown
144	var $eventName = ( isUndefined(this.selectstart) ? 'mousedown' : 'selectstart' ) + '.vDisableSelection';
145
146	this.on( $eventName, function( $e ) {
147		$e.preventDefault();
148	}); //FUNC onMouseDown
149
150} //FUNC disableSelection
151
152jQuery.fn.enableSelection = function() {
153	this.off('.vDisableSelection');
154} //FUNC enableSelection
155
156} //IF no disable seleciton
157
158function isDebug () {
159
160	if ( !isEmpty( getCookie('debug') ) )
161		return true;
162
163	if ( location.search.indexOf('debug=1') != -1 )
164		return true;
165
166	return false;
167} //FUNC isDebug
168
169function isIframe () {
170	try {
171		return window.self !== window.top;
172	} catch (e) {
173		return true;
174	}
175} //FUNC isIframe
176
177function implode(glue, obj) {
178
179	// Faster will be call .join if array given
180
181	if ( obj instanceof Array )
182		return obj.join(glue);
183
184	// Or doing manually for object
185
186	var res = '';
187
188	for ( var i in obj ) {
189		if ( res ) res += glue;
190		res += obj[i];
191	} //FOR each property
192
193	return res;
194} //FUNC implode
195
196function ucfirst ($str) {
197	return $str && $str[0].toUpperCase() + $str.slice(1);
198} //FUNC ucfirst
199
200String.prototype.capitalize = function() {
201	return ucfirst(this);
202} //FUNC capitalize
203
204if ( !String.prototype.startsWith ) {
205String.prototype.startsWith = function ($needle) {
206	return this.lastIndexOf($needle, 0) === 0;
207}} //FUNC startsWith
208
209if ( !String.prototype.endsWith ) {
210String.prototype.endsWith = function ($needle) {
211	var $lastIndex	= this.lastIndexOf($needle);
212	return ( $lastIndex != -1 ) && ( $lastIndex + $needle.length == this.length );
213}} //FUNC endsWith
214
215function strRepeat ($str, $multiplier) {
216
217	if ( !$multiplier )
218		return '';
219
220	var $res = '';
221
222	for ( var $i = 0; $i < $multiplier; $i++ ) {
223		$res += $str;
224	} //FOR multiple times
225
226	return $res;
227} //FUNC strRepeat
228
229function instanceName ($var) {
230
231	// Determining instance using basic Object.toString()
232	$res = Object.prototype.toString.call($var);
233
234	// Cutting usual [object ...] from it to get clean instance name
235	$res = $res.slice(8, -1);
236
237	return $res;
238} //FUNC instanceName
239var getClassOf = instanceName;
240
241function isClass ($var, $class) {
242	return getClassOf($var) === $class;
243} // FUNC isBool
244
245function isBool ($var) {
246	return typeof($var) == 'boolean';
247} // FUNC isBool
248
249function isNumber ($var) {
250	return typeof($var) == 'number';
251} //FUNC isNumber
252
253function isNumeric ($var) {
254	return $var !== '' && !isNaN($var) && isFinite($var);
255} //FUNC isNumeric
256
257function isInt ($var) {
258	return !isNaN($var) && (parseInt($var) == $var);
259} //FUNC isInt
260
261function isFloat ($var) {
262	return $var !== '' && !isNaN($var) && isFinite($var) && !isInt($var);
263} //FUNC isFloat
264
265function isArray ($var) {
266	return $var instanceof Array;
267} //FUNC isArray
268
269function isObject ($var, $orArray) {
270
271	// If not object - then false anyway
272	if ( typeof($var) != 'object' )
273		return false;
274
275	// If arrays allowed - we have result already
276	if ( $orArray )
277		return true;
278
279	// Now need to check if it is array
280	// Should not be array for strict check
281	return ( !isArray($var) );
282
283} //FUNC isArray
284
285var isString = isStr;
286function isStr ($var) {
287	return typeof($var) == 'string';
288} //FUNC isStr
289
290function isIn ($var, $values) {
291	return $values.indexOf($var) > -1;
292} //FUNC isIn
293
294// Global constant for undefined type checks
295var UNDEFINED = 'undefined';
296
297function isUndefined($var) {
298	return $var === void 0;
299} //FUNC isUndefined
300
301function isDefined($var) {
302	return !isUndefined($var);
303} //FUNC isDefined
304
305function setDefault($var, $default) {
306	return isDefined($var)? $var : $default;
307} //FUNC isDefined
308
309var isset = isSet;
310function isSet ($var) {
311	return !isUndefined($var);
312} //FUNC isSet
313
314var empty = isEmpty;
315function isEmpty ($var) {
316
317	// Fastest way to test
318	if ( !$var )
319		return true;
320
321	// '0' means empty too
322	if ( $var === '0' )
323		return true;
324
325	// Extra test need only for objects, so if it's not object - no need to test more
326	if ( typeof($var) !== 'object' )
327		return false;
328
329	// Testing array first (faster test)
330	if ( isArray($var) )
331		return $var.length == 0;
332
333	// If still here - its object and need to loop through to check properties
334	// Any existing property ($i) means it's not empty
335	for ( var $i in $var )
336		return false;
337
338	// If not triggered above - that's empty object
339	return true;
340} //FUNC isEmpty
341
342function asBool ($var) {
343
344	// Reacting to speciefic strings
345	if ( $var === 'false' )
346		return false;
347
348	if ( $var === 'true' )
349		return true;
350
351	return !isEmpty($var);
352} //FUNC asBool
353
354function isNumber ($var) {
355	return typeof($var) == 'number';
356} //FUNC isArray
357
358function isFunction ($var) {
359	return typeof($var) == 'function';
360} //FUNC isArray
361
362function isScalar ($var, $ex) {
363
364	// Testing common scalar types
365	if ( (/boolean|number|string/).test(typeof($var)) )
366		return true;
367
368	// Extra test assumes that NULL and undefined are scalars
369	if ( !$ex )
370		return false;
371
372	if ( typeof($var) == 'undefined' || $var === null )
373		return true;
374
375	return false;
376} //FUNC isScalar
377
378function isScalarArray ($var, $ex) {
379
380	if ( !isArray($var) )
381		return false;
382
383	// If at least one array item is not scalar - that's not scalar array
384	for ( var $i = 0; $i < $var.length; $i++ )
385		if ( !isScalar($var[$i], $ex) )
386			return false;
387
388	return true;
389} //FUNC isScalar
390
391/** //** ----= arrayPath	=--------------------------------------------------------------------------------------\**//** \
392*
393*	Traversing array using key paths. Allows to get or set values.
394*
395*	@param		array	$array		- Array to traverse.
396* 	@param		mixed	$path		- Path to navigate. Either string or array.
397* 						 E.g.: 'key1/key2/deepvalue' or ['key1', 'key2', 'deepvalue']
398* 	@param		mixed	[$value]	- Value to set for setter mode (if omited, will return value instead)
399* 	@param		string	[$divider]	- Path divider (used only if path is given as string).
400*
401*	@return		mixed			- Target value in getter mode, or new value in setter.
402*
403\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
404function arrayPath ($array, $path, $value, $divider) {
405
406	$divider = $divider || '/';
407
408	// Checking for setter mode
409	var $isSetter = ( !isUndefined($value) );
410
411	// Splitting path to individual keys
412	if ( !isArray($path) ) {
413		$path = $path.split($divider);
414	} //IF not array given
415
416	// Looping down to value in array
417	// Using refs for recurcive looping
418	// Thus saving parent for last step
419	var $var	= $array;
420	var $parent	= $array;
421
422	for ( var $i in $path ) {
423
424		$key = $path[$i];
425
426		// In setter mode - need to make sure that var is array
427		// In getter mode - if var is already not array - that's null return
428		if ( !isObject($var) || $var == null )
429			if ( $isSetter )
430				$var = [];
431			else
432				return;
433
434		// Checking for key presence
435		// In getter mode unexisting key results to NULL result
436		// In setter mode - path should be created
437		// This should be done priror next iteration to avoid source array altering
438		if ( isUndefined($var[$key]) )
439			if ( $isSetter )
440				$var[$key] = {};
441			else
442				return;
443
444		// Saving ref for next iteration
445		$parent	= $var;
446		$var	= $var[$key];
447
448	} //FOR each path key
449
450	// At this point ref points to end value
451	// Can set and return it
452	if ( $isSetter )
453		$parent[$key] = $value;
454
455	return $var;
456
457} //FUNC arrayPath
458
459if ( !Object.keys ) {
460    Object.keys = function (obj) {
461        var keys = [],
462            k;
463
464        for ( k in obj )
465            if ( Object.prototype.hasOwnProperty.call(obj, k) )
466                keys.push(k);
467
468        return keys;
469    }; //FUNC keys
470} //IF Object have no keys method
471
472/** //** ----= objSize	=----------------------------------------------------------------------------------------------\**//** \
473*
474*	Returns object properties count. Usefull as analog of [].length for data objects.
475*
476*	@param		object	$obj	- Object to count.
477*
478*	@return		int		- Object "size".
479*
480\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
481function objSize ($obj) {
482
483	var $res = 0;
484	for ( $i in $obj)
485		if ( $obj.hasOwnProperty($i) )
486			$res++;
487
488	return $res;
489} //FUNC objSize
490
491/** //** ----= objStep	=----------------------------------------------------------------------------------------------\**//** \
492*
493*	Returns object key in "step" away from given key.
494*
495*	@param		object	$obj	- Object to search key in
496*	@param		$key	$key	- Key to step from
497*	@param		$step	$step	- Step to count from given key (can be negatve to count backwards)
498*
499*	@return		string		- Found key, or FALSE if smth failed
500*
501\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
502function objStep ($obj, $key, $step) {
503
504	// Using array for indexing keys, and then searching keys in it
505	// In case smth goes wrong - FALSE is returned
506
507	var $idx = Object.keys($obj);
508
509	if ( $idx.length == 0 )
510		return false;
511
512	var $i = $idx.indexOf($key);
513
514	if ( $i < 0 )
515		return false;
516
517	// Stepping from key
518	$i += $step;
519
520	if ( $i < 0 || $i >= $idx.length )
521		return false;
522
523	return $idx[$i];
524} //FUNC objStep
525
526/** //** ----= objNext, objPrev	=--------------------------------------------------------------------------------------\**//** \
527*
528*	Common use cases of objStep for searching next/prev keys in object
529*
530*	@param		object	$obj	- Object to search key in
531*	@param		$key	$key	- Key to step from
532*
533*	@return		string		- Found key, or FALSE if smth failed
534*
535\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
536function objPrev ($obj, $key) {
537	return objStep($obj, $key, -1);
538} //FUNC objPrev
539function objNext ($obj, $key) {
540	return objStep($obj, $key, 1);
541} //FUNC objNext
542
543/** //** ----= objFirst, objLast	=------------------------------------------------------------------------------\**//** \
544*
545*	Returns first/last object key.
546*
547*	@param		object	$obj	- Object to search key in
548*
549*	@return		string		- Found key, or FALSE if smth failed
550*
551\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
552function objFirst ($obj) {
553
554	var $idx = Object.keys($obj);
555
556	if ( $idx.length == 0 )
557		return false;
558
559	return $idx[0];
560} //FUNC objFirst
561function objLast ($obj) {
562
563	var $idx = Object.keys($obj);
564
565	if ( $idx.length == 0 )
566		return false;
567
568	return $idx[$idx.length-1];
569} //FUNC objLast
570
571/** //** ----= isSame	=----------------------------------------------------------------------------------------------\**//** \
572*
573* 	Compares two objects given. Designed for data objects.
574*
575*	@param	object	x, y		- Objects to compare.
576*	@param	bool	[oneway]	- Set TRUE to test only by x values (i.e y can be bigger, in other words - if X is in Y)
577*	@param	bool	[presort]	- Set TRUE to presort incoming arrays. This may
578*					  be necessary if comparing arrys in order
579*					  independent way. Usefull for values lists.
580*
581\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
582function isSame (x, y, oneway, presort) {
583
584	// Fast check for nulls / empties
585	if ( !x || !y ) {
586
587		if ( !x && y ) return false;
588		if ( x && !y ) return false;
589
590		return true;
591
592	} //IF some is null or empty
593
594	// IF arrays come - first better check lengths
595	if ( x instanceof Array && y instanceof Array ) {
596
597		if ( x.length != y.length )
598			return false;
599
600		if ( presort ) {
601			x.sort();
602			y.sort();
603		} //IF presort seet
604
605	} //IF arrays come
606
607	// First checking properties existance.
608	// After this check full comparasions will be done in opposite direction
609
610	if ( !oneway ) {
611		for ( var p in y ) {
612			if ( typeof(x[p]) == 'undefined')
613				return false;
614		} //FOR each property in y
615	} //IF not one way comparasion
616
617	// Type based checking, in opposite comparasion direction
618	for ( var p in x ) {
619
620		// Checking self properties in oppose object, jsut existance first
621		if ( typeof(y[p]) == 'undefined' )
622			return false;
623
624		if ( x[p] ) { // Fast symantec check, everything that is logically FALSE - no need to check by type
625
626			switch( typeof(x[p]) ) {
627
628				case 'object' :
629
630					// Checking objects recursively
631					// This allows multidimensional objects checks,
632					// But can possibly hang browser. Normally will not.
633					// ToDo: prevent possible reqursions
634					if ( !isSame(x[p], y[p], oneway, presort) )
635						return false;
636
637					break;
638
639				case 'function' :
640
641					// Of course toString is not best way to compare functions.
642					// But normally same named funcitons should have same source code,
643					// and it's anyway better and faster than to full syntax parsing.
644					// Fast toString comparation will work in most typical cases.
645					// Just don't use this function if U need to compare functions in objects so much!.
646					if ( this[p].toString() != x[p].toString() )
647						return false;
648
649					break;
650				default:
651
652					// At last simple check that will usually used :).
653					if ( x[p] != y[p] )
654						return false;
655
656			} //SWITCH type of x
657
658		} else { //IF is value
659
660			// Checking same property on other object
661			if ( y[p] )
662				return false;
663
664		} //If false value
665
666	} //FOR each property in x
667
668	return true;
669} //FUNC isSame
670
671function isXHR2 () {
672
673	if ( !window.FormData )
674		return false;
675
676	// Testing for XMLHttpRequest Level 2
677	var xhr = new XMLHttpRequest();
678	if ( !xhr.upload )
679		return false;
680
681	return true;
682} //FUNC isXHR2
683
684function isFilesAPI () {
685
686	if ( !isXHR2() )
687		return false;
688
689	if ( !(window.File && window.FileList && window.FileReader) )
690		return false;
691
692	return true;
693} //FUNC isFilesAPI
694
695function isIos () {
696	return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
697} //FUNC isIos
698
699/** //** ----= isTouchScreen	=--------------------------------------------------------------------------------------\**//** \
700*
701*	Tests if device is touch screen enabled device.
702*
703* 	@return bool			- TRUE if device supports touchs screen. (i.e. pointer:coarse from css4 media queries.)
704*
705\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
706function isTouchScreen () {
707
708	var $res = 'ontouchstart' in document.documentElement;
709
710	return $res;
711
712} //FUNC isTouchScreen
713
714/** //** ----= isJQ	=----------------------------------------------------------------------------------------------\**//** \
715*
716*	Tests if given object is jQuery element
717*
718*	@param		MIXED	$val	- Value to check.
719*
720*	@return		bool		- Check result.
721*
722\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
723function isJQ ($val) {
724
725	// Empty value is not jQuery
726	if ( !$val )
727		return false;
728
729	return ($val instanceof jQuery || $val.jquery);
730} //FUNC isJQ
731
732/** //** ----= _jq	=----------------------------------------------------------------------------------------------\**//** \
733*
734* 	Ensures that given parameter is valid jQuery object. Avoids jQuery object clone.
735*
736*	@param	MIXED	$element	- jQuery selector, DOM element or jQuery object.
737*	@param	MIXED	[$context]	- Valid jQuery context.
738*
739*	@return	object(jQuery)		- jQuery object.
740*
741\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
742function _jq ($element, $context) {
743
744	if ( !isJQ($element) )
745		return jQuery($element, $context);
746
747	return $element;
748} //FUNC _jq
749
750function formatFileSize (bytes) {
751
752	if ( !bytes ) return bytes;
753
754	var labels	= ['b','Kb','Mb','Gb','Tb','Pb','Eb','Zb','Yb'];
755	var ex		= Math.floor( Math.log(bytes) / Math.log(1024) );
756
757	var res		= bytes / Math.pow(1024, ex);
758
759	return res.toFixed(2) + ' ' + labels[ex];
760} //FUNC formatFileSize
761
762/** //** ----= setObjectOptions	=--------------------------------------------------------------------------------------\**//** \
763*
764*	Initiates object properties from given data object. Sets properties directly, without test if property really existed.
765*	Essentially copies one object properties into another.
766*
767* 	@param	object	$object		- Object to apply options to.
768* 	@param	array	$options	- Options to set.
769*
770* 	@return object			- Returns given object.
771*
772\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
773function setObjectOptions ($object, $options) {
774
775	$options = $options || {};
776
777	// Looping through each option given and setting it as property
778	for ( var $opt in $options )
779		$object[$opt] = $options[$opt];
780
781	return $object;
782} //FUNC setObjectOptions
783
784/** //** ----= borderValue	=--------------------------------------------------------------------------------------\**//** \
785*
786* 	Ensures that given value is within bounds.
787*
788*	@param	MIXED	$element	- jQuery selector, DOM element or jQuery object.
789*	@param	MIXED	[$context]	- Valid jQuery context.
790*
791*	@return	object(jQuery)		- jQuery object.
792*
793\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
794function borderValue ($value, $min, $max) {
795
796	if ( $value < $min )
797		$value = $min;
798
799	if ( $value > $max )
800		$value = $max;
801
802	return $value;
803
804} //FUNC borderValue
805
806/** //** ----= touchToMouse	=--------------------------------------------------------------------------------------\**//** \
807*
808*	Enables translation of touch events into mouse events.
809*
810*	@param	DOMElement	$el	- Element to apply to.
811*
812*	@return SELF
813*
814\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
815jQuery.fn.touchToMouse = function () {
816
817	if ( !this.length )
818		return;
819
820	// Enabling touches for each element in set
821	this.each( function () {
822		touchToMouse(this);
823	}); //each element
824
825} //FUNC touchToMouse
826
827function touchToMouse ( $el ) {
828
829	// Using solution found in internet with slight tweaks and adding explanation of what is going on
830	// Basically - capturing touch events, creating similar mouse event and rethrowing it instead
831
832	// Using event wrapper to simplify code
833	var $handler = function ( $event ) {
834
835		// Using first element (you can't have multitouch with mouse :) )
836		var $touchEvent = $event.changedTouches[0];
837
838		// Defining event type from subst table
839		var $eventType	= {
840			touchstart	: 'mousedown',
841			touchmove	: 'mousemove',
842			touchend	: 'mouseup',
843		}[$event.type]; //$types
844
845		// Using only translatable events, otherwise - returning
846		if ( !$eventType )
847			return;
848
849		// Creating new mouse event
850		// And initializing with data from captured touch event
851		var $mouseEvent = document.createEvent('MouseEvent');
852		$mouseEvent.initMouseEvent(
853			$eventType, true, true, window, 1,
854			$touchEvent.screenX, $touchEvent.screenY,
855			$touchEvent.clientX, $touchEvent.clientY, false,
856			false, false, false, 0, null
857		); //initMouseEvent
858
859		// Rethrowing it from same target as original touch
860		$touchEvent.target.dispatchEvent($mouseEvent);
861
862		// Clearing bubbling
863		event.preventDefault();
864
865	} //FUNC hanlder
866
867	// Adding custom handler
868	$el.addEventListener('touchstart', $handler, true);
869	$el.addEventListener('touchmove', $handler, true);
870	$el.addEventListener('touchend', $handler, true);
871	$el.addEventListener('touchcancel', $handler, true);
872
873} //FUNC touchToMouse
874
875/** //** ----= observeChange	=--------------------------------------------------------------------------------------\**//** \
876*
877*	Adds MutationObserver to observer changes in input value. Triggers change when value updates.
878*	Good use for hidden and text based inputs, to have proper/imideate change.
879*
880*	@param	DOMElement	$el	- Element to apply to.
881*
882*	@return SELF
883*
884\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
885jQuery.fn.observeChange = function () {
886
887	if ( !this.length )
888		return;
889
890	// Enabling touches for each element in set
891	this.each( function () {
892		observeChange(this);
893	}); //each element
894
895} //FUNC observeChange
896
897function observeChange ( $el ) {
898
899	// Using solution found in internet with slight tweaks and adding explanation of what is going on
900
901	// Creating MutationObserver (compatable with older webkit), and watching value attribute of element given (supposedly input)
902	// Once value changed - triggering change with jQuery
903
904	// Preparing class, to be compatable with older webkit
905	// Doing it globally, does not hurt anything
906	MutationObserver	= window.MutationObserver || window.WebKitMutationObserver;
907
908	// Saving observer in input, just in case
909	// Adding callback that will check what's changed
910	$el.vObserver	= new MutationObserver( function ( $mutations, $observer ) {
911
912		// Should be only one mutation really
913		// Interested in value change
914		if ( $mutations[0].attributeName == 'value') {
915
916			// Using mutation target to trigger
917			// Since it's basically a closure - can reference give element directly
918			// Wrapping with jQuery if necessary
919			_jq($el).trigger('change');
920
921		} //IF value changed
922
923	}); //FUNC MutationObserver.callback
924
925	// Watching element attributes
926	$el.vObserver.observe($el, {
927		attributes	: true,
928	}); //observe
929
930	// Done here
931
932} //FUNC observeChange
933
934/** //** ----= vEventObject	=--------------------------------------------------------------------------------------\**//** \
935*
936* 	Extends given object to accept events callbacks. Allows events registering and chain calling later. Callback will
937*	run within object's context and accept parameters given to event trigger.
938*
939*	@param	array	types	- List of event types to create.
940*
941*	@param	object	obj	- Object to extend.
942*
943*	@return	object		- Modified object.
944*
945\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
946function vEventObject (types, obj) {
947
948	obj = obj || {};
949
950	// Creating callbacks storage in parent
951	if ( isEmpty(obj['__events']) )
952		obj['__events'] = {};
953
954// ---- BIND/RUNNER ----
955
956	/** //** ----= _runevent	=------------------------------------------------------------------------------\**//** \
957	*
958	* 	For Internal Use. Event runner, used to call events, or set new ones (in case if callback function given).
959	*
960	* 	@param	string	type	- Event type to use.
961	*
962	*	@return	MIXED			- Mixed return.
963	*		SELF			- If setting event.
964	*		bool			- Boolean FALSE in even return - interrupts chain, and also is returned.
965	*					  TRUE is just returned.
966	*		VOID			- Other cases.
967	*
968	\**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
969	obj._runevent = function ( type, args ) {
970
971		// Setting callback if given as first argument
972		if ( args[0] && typeof(args[0]) == 'function' ) {
973			this.__events[type].push(args[0]);
974			return obj;
975		} //IF callback set
976
977		var res = false;
978
979		// If no callback given (getter mode) - running all calbacks of that type, cb should contain arguments then
980		for ( var func in this.__events[type] ) {
981			var eres = this.__events[type][func].apply(obj, args);
982
983			// False in result means even chain interruption, returning it to parent also
984			if ( eres === false )
985				return false;
986
987			// True in one of events means smth for caller, we'll return it later
988			if ( eres === true )
989				res = true;
990
991		} //FOR each callback
992
993		// If someone return true - we notify parent about, else - undefined return
994		if ( res )
995			return res;
996
997	} //FUNC _runevent
998
999// ---- UNBIND ----
1000
1001	/** //** ----= unbind	=--------------------------------------------------------------------------------------\**//** \
1002	*
1003	* 	Event remover. Unbings given event type, or given callback if specified. If no parameters specified -
1004	*	unbinding all events (usefull to get clean object).
1005	*
1006	* 	@param	string		[type]	- Event type to unbind.
1007	*	@param	function	[fn]	- Callback to unbind within type.
1008	*
1009	*	@return	SELF
1010	*
1011	\**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
1012	obj.unbind = function (type, fn) {
1013
1014		var $this = this;
1015
1016		// Event clearing helper
1017		function unbindEvent (e) {
1018
1019			// Deleting only speciefic events, skipping body ones
1020			for ( var i = 0; i < e.length; i++ ) {
1021
1022				// Skipping body ones
1023				if ( e[i]._bodyeventfunction ) continue;
1024
1025				// Skipping all non given (if some given)
1026				if ( fn && e[i] !== fn ) continue;
1027
1028				e.splice(i, 1);
1029
1030			} //FOR each callback
1031
1032		}; //FUNC unbindEvent
1033
1034		// If type specified - cleaning only that type, otherwise - all of them
1035		if ( type )
1036			unbindEvent(this.__events[type]);
1037		else
1038			for ( var i in this.__events )
1039				unbindEvent(this.__events[i]);
1040
1041		return obj;
1042
1043	}; //FUNC obj.unbind
1044
1045// ---- SHORTCUTS ----
1046
1047	// Creating shortcut for each event
1048	for ( var ev in types ) {
1049
1050		var type = types[ev];
1051
1052		// For each type we have own array with callbacks
1053		if ( isEmpty(obj.__events[type]) )
1054			obj.__events[type] = [];
1055
1056		// Existing event functions became first events
1057		if ( isFunction(obj[type]) ) {
1058
1059			// Skipping event functions
1060			if ( obj[type]._runeventfunction )
1061				continue;
1062			else {
1063				// Marking as body function - those can't be unbind
1064				obj[type]._bodyeventfunction = 1;
1065				obj._runevent(type, [obj[type]]);
1066			} //IF own function
1067
1068		} //IF function already exists in body
1069
1070		// Creating event trigger function in parent for each type
1071		obj[type] = function (t) { return function () { return this._runevent(t, arguments);};}(type);
1072
1073		// Marking as event function to recognise later
1074		obj[type]._runeventfunction = 1;
1075
1076	} //FOR each type
1077
1078	return obj;
1079} //FUNC vEventObject
1080
1081/** //** ----= PromiseEx	=--------------------------------------------------------------------------------------\**//** \
1082*
1083* 	Special promise version with outside controllers (custom resolve/reject methods).
1084*
1085*	@param	function	$executor	- Promise executor.
1086*
1087*	@return	object				- Modified promise.
1088*
1089\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
1090var PromiseEx = function ( $executor ) {
1091
1092	// Saving controls outisde
1093	var $resolve, $reject;
1094
1095	var $res = new Promise ( function (resolve, reject) {
1096
1097		// Saving resolve and reject for later reuse
1098		$resolve = resolve;
1099		$reject = reject;
1100
1101		// Running executor as normal, it might resolve/reject as necessary
1102		if ( isFunction($executor) )
1103			$executor(resolve, reject);
1104
1105		// Done here
1106
1107	}); //Promise
1108
1109	// Saving calls in object itself
1110	$res.doResolve	= $resolve;
1111	$res.doReject	= $reject;
1112
1113	return $res;
1114
1115} //promiseEx
1116
1117/** //** ----= reloadCSS		 =--------------------------------------\**//** \
1118*
1119* 	Forces browser to reload CSS sheets dynamically.
1120*
1121*	@param	string	url	- CSS sheet URL.
1122*
1123\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
1124function reloadCSS (url) {
1125
1126	var salt	= randomString();
1127	var salt_url	= url + '?reload=' + salt;
1128
1129	var new_sheet = jQuery('<link rel="stylesheet" href="' + salt_url + '" type="text/css" />');
1130	var old_sheet = jQuery('LINK[href*="' + url + '"]');
1131
1132	if ( document.createStyleSheet ) {
1133		document.createStyleSheet(salt_url);
1134	} else { //IF IE
1135		jQuery('HEAD').append( new_sheet );
1136	} //IF normal browsers
1137
1138	// Removing old sheet if present.
1139	setTimeout( function () { old_sheet.remove(); }, 1000);
1140
1141} //FUNC reloadCSS
1142
1143/** //** ----= countElements	 =----------------------------------------------\**//** \
1144*
1145* 	Returns overal page's elements count. Usefull for optimization.
1146*
1147*	@param	jQuery	el	- Count elements within give element.
1148*
1149*	@return int		- Elements count.
1150*
1151\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
1152function countElements (el) {
1153
1154	if ( !el )
1155		return document.getElementsByTagName('*').length;
1156
1157	return jQuery(el).find('*').length;
1158} //FUNC countElements
1159
1160function randomString(type, length) {
1161
1162	if ( !type ) type = 'alnum';
1163	if ( !length ) length = 8;
1164
1165	var chars = '';
1166
1167	switch ( type.toLowerCase() ) {
1168		case 'alnum'	: chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
1169			break;
1170		case 'alpha'	: chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
1171			break;
1172		case 'hex'	: chars = '0123456789ABCDEF';
1173			break;
1174		case 'caps'	: chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
1175			break;
1176		case 'capnum'	: chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
1177			break;
1178		case 'numeric'	: chars = '0123456789';
1179			break;
1180		case 'nozero'	: chars = '123456789';
1181			break;
1182		case 'keyb'	: chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ :;,.\'"\|/?[]{}()<>~`!@#$%^&*-=_+';
1183			break;
1184
1185		default		: chars = type;
1186	} //SWITCH $type
1187
1188	if ( !chars ) return '';
1189
1190	var str = '';
1191
1192	for (var i = 0; i < length; i++) {
1193		var rnum = Math.floor(Math.random() * chars.length);
1194		str += chars.substring(rnum, rnum + 1);
1195	}
1196
1197	return str;
1198} //FUNC randomString
1199
1200/** //** ----= newSN	 =---------------------------------------------------------------------------------------------\**//** \
1201*
1202*	Generates new random SN. SN is usually capnum unique string of 16 chars, starting from give char.
1203*
1204*	@param		string	[$prefix]	- Limit SN to start only with this char.
1205*	@param		string	[$length]	- SN length, 16 by default.
1206*
1207*	@return		string			- Random SN string.
1208*
1209\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
1210function newSN ($prefix, $length) {
1211
1212	$prefix = $prefix || '';
1213	$length	= $length || 16;
1214
1215	return ($prefix + randomString('capnum', $length)).substring(0, $length);
1216} //FUNC newSN
1217
1218/** //** ----= fileName		 =----------------------------------------------\**//** \
1219*
1220* 	Extracts file name from full path.
1221*
1222* 	@param	string	path	- Full path and file name.
1223*	@return	string		- File name.
1224*
1225\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
1226function fileName (path) {
1227	if ( !path ) return '';
1228	return path.replace(/^.*\\/, '');
1229} //FUNC fileName
1230
1231/** //** ----= fileExt		 =----------------------------------------------\**//** \
1232*
1233* 	Extracts file extension from file name.
1234*
1235* 	@param	string	file	- Full path and file name.
1236*	@return	string		- File name.
1237*
1238\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
1239function fileExt (file) {
1240	var tmp	= file.lastIndexOf('.');
1241
1242	if ( !tmp ) return false;
1243
1244	return file.substr(tmp+1, file.length);
1245
1246} //FUNC fileExt
1247
1248/** //** ----= fileType	 =---------------------------------------------------------------------------------------------\**//** \
1249*
1250*	Detects one of general file types: image, doc, video, music etc.
1251*
1252*	@param		string	$file		- File name to test.
1253*
1254*	@return		string			- File type.
1255*
1256\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
1257function fileType ( $file ) {
1258
1259	// Listing known file types by extensions
1260	// Simplified version. Complete version should be generated by php from mimes. To be implemented.
1261	var $types	= {
1262
1263		// ToDo: add executables
1264
1265		'php'	: 'script',
1266		'php4'	: 'script',
1267		'php5'	: 'script',
1268		'js'	: 'script',
1269		'css'	: 'script',
1270		'html'	: 'script',
1271		'htm'	: 'script',
1272		'html5'	: 'script',
1273		'html4'	: 'script',
1274		'cgi'	: 'script',
1275
1276		'jpeg'	: 'image',
1277		'jpg'	: 'image',
1278		'jpe'	: 'image',
1279		'png'	: 'image',
1280		'bmp'	: 'image',
1281		'gif'	: 'image',
1282		'webp'	: 'image',
1283		'svg'	: 'image',
1284		'tiff'	: 'image',
1285		'tif'	: 'image',
1286
1287		'avi'	: 'video',
1288		'flv'	: 'video',
1289		'f4v'	: 'video',
1290		'mpeg'	: 'video',
1291		'mpg'	: 'video',
1292		'mpe'	: 'video',
1293		'mov'	: 'video',
1294		'mp4'	: 'video',
1295		'm4v'	: 'video',
1296		'wmv'	: 'video',
1297		'ogv'	: 'video',
1298		'webm'	: 'video',
1299		'mkv'	: 'video',
1300		'qt'	: 'video',
1301		'movie'	: 'video',
1302
1303		'mp2'	: 'audio',
1304		'mp3'	: 'audio',
1305		'wav'	: 'audio',
1306		'wma'	: 'audio',
1307
1308		'doc'	: 'doc',
1309		'docx'	: 'doc',
1310		'txt'	: 'doc',
1311		'text'	: 'doc',
1312		'xls'	: 'doc',
1313		'xlsx'	: 'doc',
1314		'pdf'	: 'doc',
1315
1316	}; //$ex
1317
1318	// Getting file extension, need it in lowercase
1319	var $ext	= fileExt($file) || '';
1320	$ext		= $ext.toLowerCase();
1321
1322	// Checking it it's known
1323	if ( $types[$ext] )
1324		return $types[$ext];
1325
1326	// Nothing to return if unknown
1327	return '';
1328
1329} //FUNC fileType
1330
1331function isFileScript ( $file ) {
1332	return fileType($file) === 'script';
1333} //FUNC isFileScript
1334function isFileImage ( $file ) {
1335	return fileType($file) === 'image';
1336} //FUNC isFileImage
1337function isFileVideo ( $file ) {
1338	return fileType($file) === 'video';
1339} //FUNC isFileVideo
1340function isFileAudio ( $file ) {
1341	return fileType($file) === 'audio';
1342} //FUNC isFileAudio
1343function isFileDoc ( $file ) {
1344	return fileType($file) === 'doc';
1345} //FUNC isFileDoc
1346
1347
1348/*--------------------------------------------------------------------------------*\
1349|	Humanize
1350|----------------------------------------------------------------------------------
1351| Ensures that number will be displayed as normal value (fix for JavaScript numbers)
1352| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1353|	Params:
1354|		[base]	int	- Base value to round value to.
1355|	Return:
1356|			string	- Human looking number rounded to certain base.
1357\*--------------------------------------------------------------= by Mr.V!T =-----*/
1358Number.prototype.Humanize = Number.prototype.humanize = function (base) {
1359
1360	base = base || 10;
1361
1362	var tmp = this.toFixed(base) + '';
1363	return tmp;
1364
1365	var res = tmp.rtrim('0.');
1366	if ( res == '' ) res = '0';
1367
1368	return res;
1369} //FUNC Humanize
1370
1371/*--------------------------------------------------------------------------------*\
1372|	indexOf
1373|----------------------------------------------------------------------------------
1374| Fixes indexOf for IE6.
1375| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1376|	Params:
1377|		obj		MIXED	- Item to search.
1378|		fromIndex	integer	- Search starting from index.
1379|	Return:
1380|				integer	- Item position in array, or -1 if not found.
1381\*--------------------------------------------------------------= by Mr.V!T =-----*/
1382/**/
1383if ( !Array.prototype.indexOf )
1384Array.prototype.indexOf = function (obj, fromIndex) {
1385
1386	if ( !fromIndex ) fromIndex = 0;
1387
1388	for ( var i in this )
1389		if ( this[i] === obj ) return i;
1390
1391	return -1;
1392} //FUNC indexOf
1393/**/
1394
1395/*--------------------------------------------------------------------------------*\
1396|	arrayJoin
1397|----------------------------------------------------------------------------------
1398| Extended join for arrays.
1399| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1400|	Params:
1401|		array		array	- Array to process.
1402|		separator	string	- String to use as separator.
1403|		include_keys	bool	- Set TRUE to encode keys in result string.
1404|	Return:
1405|				string	- Array as string.
1406\*--------------------------------------------------------------= by Mr.V!T =-----*/
1407function arrayJoin (array, separator, include_keys) {
1408
1409	if ( !separator ) separator = ',';
1410
1411	var res = '';
1412
1413	var j = 0;
1414
1415	for ( var i in array ) {
1416
1417		if ( typeof(array[i]) == 'function' ) continue;
1418
1419		if ( res ) res += separator;
1420
1421		if ( include_keys ) {
1422
1423			if ( i != j )
1424				res += i + ' = ';
1425
1426		} //IF need to include keys
1427
1428		res += array[i];
1429		j++;
1430
1431	} //FOR each item
1432
1433	return res;
1434} //FUNC arrayJoin
1435
1436/*--------------------------------------------------------------------------------*\
1437|	arraySplit
1438|----------------------------------------------------------------------------------
1439| Splits array. Extended version with keys support.
1440| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1441|	Params:
1442|		string		string	- String to process.
1443|		separator	string	- String to use as separator.
1444|		auto_tirm	string	- Allow to trim values on split.
1445|	Return:
1446|				array	- Array with values.
1447\*--------------------------------------------------------------= by Mr.V!T =-----*/
1448function arraySplit (string, separator, auto_tirm) {
1449
1450	var res	= [];
1451	var tmp = string.split(separator);
1452
1453	for ( var i in tmp ) {
1454
1455		var pos = tmp[i].indexOf('=');
1456
1457		if ( pos != -1 ) {
1458
1459			var key = tmp[i].substr(0, pos);
1460			if ( auto_tirm ) key = key.trim();
1461
1462			var val = tmp[i].substr(pos+1);
1463			if ( auto_tirm ) val = val.trim();
1464
1465			res[key] = val;
1466
1467		} else { //IF eq symbol found
1468
1469			if ( auto_tirm ) tmp[i] = tmp[i].trim();
1470			res.push(tmp[i]);
1471
1472		} //IF single value
1473
1474	} //FOR each value
1475
1476	return res;
1477} //FUNC arraySplit
1478
1479String.prototype.limit = function(l, append) {
1480
1481	if ( this.length <= l )
1482		return this.toString();
1483
1484	append = append || '&hellip;';
1485	al = append.substr(0, 1) == '&' ? 1 : append.length;
1486
1487	return this.substr(0, l - al) + append;
1488} //FUNC limit
1489
1490String.prototype.ucfirst = function() {
1491
1492	// Nothing to do with empty string
1493	if ( !this.length ) return this;
1494
1495	return this.charAt(0).toUpperCase() + this.substr(1);
1496} //FUNC ucfirst
1497
1498/*--------------------------------------------------------------------------------*\
1499|	escape
1500|----------------------------------------------------------------------------------
1501| Escapes string for using in REGex.
1502| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1503|	Params:
1504|		NONE
1505|	Return:
1506|		NULL
1507\*--------------------------------------------------------------= by Mr.V!T =-----*/
1508String.prototype.escape = function() {
1509	return this.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!<>\|\:])/g, '\\$1');
1510} //FUNC escape
1511
1512/*--------------------------------------------------------------------------------*\
1513|	_trim
1514|----------------------------------------------------------------------------------
1515| Base function for trimming strings.
1516| ***TNX*** Ideas taken from phpjs.org
1517| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1518|	Params:
1519|		[charlist]	string	- Optional characteres to trim.
1520|		[left]		bool	- Trim left.
1521|		[right]		bool	- Trim right.
1522|	Return:
1523|				string	- Trimmed string.
1524\*--------------------------------------------------------------= by Mr.V!T =-----*/
1525String.prototype._trim = function(charlist, left, right) {
1526
1527	var str = this;
1528
1529	if ( !str )
1530		return this;
1531
1532	charlist = (charlist) ? charlist.escape() : ' \\n\\t\\s\u00A0';
1533
1534	if ( left ) str	= str.replace(new RegExp('^[' + charlist + ']+', 'gm'), '');
1535	if ( right ) str = str.replace(new RegExp('[' + charlist + ']+$', 'gm'), '');
1536
1537	return str;
1538} //FUNC _trim
1539
1540/*--------------------------------------------------------------------------------*\
1541|	ltrim
1542|----------------------------------------------------------------------------------
1543| Strips whitespace from the beginning of a string.
1544| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1545|	Params:
1546|		[charlist]	string	- Optional characteres to trim.
1547|	Return:
1548|				string	- Trimmed string.
1549\*--------------------------------------------------------------= by Mr.V!T =-----*/
1550String.prototype.ltrim = function(charlist) {
1551	return this._trim(charlist, 1, 0);
1552} //FUNC ltrim
1553
1554/*--------------------------------------------------------------------------------*\
1555|	rtrim
1556|----------------------------------------------------------------------------------
1557| Removes trailing whitespace.
1558| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1559|	Params:
1560|		[charlist]	string	- Optional characteres to trim.
1561|	Return:
1562|				string	- Trimmed string.
1563\*--------------------------------------------------------------= by Mr.V!T =-----*/
1564String.prototype.rtrim = function(charlist) {
1565	return this._trim(charlist, 0, 1);
1566} //FUNC rtrim
1567
1568/*--------------------------------------------------------------------------------*\
1569|	trim
1570|----------------------------------------------------------------------------------
1571| Removes whitespaces from both sides.
1572| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1573|	Params:
1574|		[charlist]	string	- Optional characteres to trim.
1575|	Return:
1576|				string	- Trimmed string.
1577\*--------------------------------------------------------------= by Mr.V!T =-----*/
1578String.prototype.trim = function(charlist) {
1579	return this._trim(charlist, 1, 1);
1580} //FUNC trim
1581
1582/*--------------------------------------------------------------------------------*\
1583|	xtrim
1584|----------------------------------------------------------------------------------
1585| Very fast function for trimming strings.
1586| ***TNX*** Big thanx for Steve at steves_list (at) hotmail.com.
1587| ***TNX*** http://blog.stevenlevithan.com/
1588| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1589|	Params:
1590|		NONE
1591|	Return:
1592|		NULL
1593\*--------------------------------------------------------------= by Mr.V!T =-----*/
1594String.prototype.xtrim = function() {
1595	var str = this;
1596	str = str.replace(/^\s+/, '');
1597	for (var i = str.length - 1; i >= 0; i--) {
1598		if (/\S/.test(str.charAt(i))) {
1599			str = str.substring(0, i + 1);
1600			break;
1601		}
1602	}
1603	return str;
1604} //FUNC xtrim
1605
1606/*--------------------------------------------------------------------------------*\
1607|	multiClean
1608|----------------------------------------------------------------------------------
1609| Cleans double repeated characters. E.g. doublespaces.
1610| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1611|	Params:
1612|		[character]	string	- Optional character to clean.
1613|	Return:
1614|				string	- Result string.
1615\*--------------------------------------------------------------= by Mr.V!T =-----*/
1616String.prototype.multiClean = function(character) {
1617
1618	character = character || ' ';
1619
1620	return this.replace(new RegExp('[' + character.escape() + ']{2,}', 'g'), character);
1621} //FUNC multiClean
1622
1623/*--------------------------------------------------------------------------------*\
1624|	toSafe
1625|----------------------------------------------------------------------------------
1626| Generates safe value from give string. I.E. safe to use as variable names.
1627| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1628|	Params:
1629|		[separator]	string	- Optional characteres to use as word
1630|					separator.
1631|	Return:
1632|				string	- Result string.
1633\*--------------------------------------------------------------= by Mr.V!T =-----*/
1634String.prototype.toSafe = function(separator) {
1635
1636	if ( !separator )
1637		separator = '_';
1638
1639	var res = this;
1640	res = res.replace(/[^a-zA-Z0-9_]/g, separator);
1641	res = res.multiClean(separator);
1642	res = res.trim(separator);
1643
1644	return res;
1645} //FUNC toSafe
1646
1647/*--------------------------------------------------------------------------------*\
1648|	compilePath
1649|----------------------------------------------------------------------------------
1650| Compile path from several pieces using '/' as glue.
1651| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1652|	Params:
1653|		*	string	- One or several path pieces.
1654|	Return:
1655|			string	- Valid path.
1656\*--------------------------------------------------------------= by Mr.V!T =-----*/
1657function compilePath () {
1658
1659	var len = arguments.length;
1660	if ( len == 1 ) return arguments[0];
1661
1662	var res = (arguments[0]+'').rtrim('/');
1663
1664	for (var i = 1; i < len; i++ ) {
1665		res += '/' + (arguments[i]+'').ltrim('/');
1666	} //FOR each argument
1667
1668	return res;
1669} //FUNC compilePath
1670var compileUrl = compilePath;
1671
1672/** //** ----= arraySelectKey	 =----------------------------------------------\**//** \
1673*
1674*	Chooses existing key from list given in associated array.
1675*
1676*	@param	array	array	- Source array.
1677*
1678* 	@param	MIXED	keys
1679* 		array		- Array with possible keys.
1680* 		string		- Single key for case insensitive search or regEx
1681* 				  mask for possible keys (slower).
1682*
1683*	@param	bool	[regex]	- Search mode for string key.
1684*
1685*	@return	MIXED
1686* 		string		- Existing key.
1687* 		bool		- FALSE if none exists.
1688*
1689\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
1690function arraySelectKey (array, keys, regex) {
1691
1692	if ( typeof(keys) == 'object' ) {
1693
1694		for ( var i = 0; i < keys.length; i++ ) {
1695
1696			if ( array[keys[i]] != undefined ) return keys[i];
1697
1698		} //FOR each key
1699
1700	} else { //IF searching by array
1701
1702		var reg	= keys;
1703		if ( !regex )
1704			reg = new RegExp('^' + keys.escape() + '$', 'i');
1705
1706		for ( var key in array ) {
1707
1708		//	__(key);
1709
1710			if ( reg.test(key) ) return key;
1711		} //FOR each
1712
1713	} //IF searshing by regex
1714
1715	return undefined;
1716} //FUNC arraySelectKey
1717
1718/** //** ----= arraySelectValue	 =----------------------------------------------\**//** \
1719*
1720*	Chooses value by one of existing keys given.
1721*
1722*	@param	array	array		- Source array.
1723*	@param	array	keys		- Array with possible keys.
1724*	@param	MIXED	[default]	- Default value to use if nothing found.
1725*
1726*	@return	MIXED			- Found value or default if none found.
1727*
1728\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
1729function arraySelectValue (array, keys, def) {
1730
1731	var key = arraySelectKey(array, keys);
1732
1733	if ( !key || !array[key] == undefined ) return def;
1734
1735	return array[key];
1736} //FUNC arraySelectValue
1737
1738/*--------------------------------------------------------------------------------*\
1739|	arrayToPost
1740|----------------------------------------------------------------------------------
1741| Prepares multidimentional array to post in native PHP format.
1742| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1743|	Params:
1744|		array	object	- Common JavaScript array object.
1745|	Return:
1746|			array	- Array in POST format.
1747\*--------------------------------------------------------------= by Mr.V!T =-----*/
1748function arrayToPost (array, prefix) {
1749
1750	var res = {};
1751
1752	for ( i in array ) {
1753
1754		var key = ( prefix )? prefix + '[' + i + ']' : i;
1755
1756		if ( typeof(array[i]) == 'object' ) {
1757
1758			var sub = arrayToPost(array[i], key);
1759
1760			for ( j in sub ) res[j] = sub[j];
1761
1762		} else { //IF sub array
1763			res[key] = array[i];
1764		} //IF other type
1765
1766	} //FOR each array
1767
1768	return res;
1769} //FUNC arrayToPost
1770
1771/** //** ----= submitUrl	=--------------------------------------------------------------------------------------\**//** \
1772*
1773*	Submits given data as POST/GET to given url. Literally simulates form submit.
1774*
1775*	@param		string	$url		- Url to submit to.
1776*	@param		object	$data		- Data to submit.
1777*	@param		string	[$blank]	- Set TRUE to open in new tab.
1778*
1779*	@return		bool			- Always FALSE.
1780*
1781\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
1782function submitUrl($url, $data, $blank) {
1783
1784	$method	= 'post';	// No real need to have method optional
1785	$data	= $data || {};
1786	$target	= '';
1787
1788	if ( $blank )
1789		$target = ' target="_blank"';
1790
1791	// Generating form html as string and appending it to body
1792	// Each data will be hidden input in form
1793	var $f = '<form method="' + $method + '" action="' + $url + '"' + $target + ' style="display:none">';
1794
1795	for ( $i in $data ) {
1796
1797		$f += '<input type="hidden" name="' + $i + '" value="' + $data[$i] + '" />';
1798
1799	} //FOR each data
1800
1801	$f += '</form>';
1802
1803	// Appending form, getting it's element, and submiting
1804	var $el = jQuery($f).appendTo('BODY').submit();
1805
1806	return false;
1807
1808} //FUNC submitUrl
1809
1810/** //** ----= parseVariables	=--------------------------------------------------------------------------------------\**//** \
1811*
1812*	Parses {varables} in a template. Supporting complex vairables like {var-sub} and {var.sub}
1813*
1814*	@param		string	$str		- Template to parse.
1815*	@param		object	$vars		- Data object with variable to parse.
1816*	@param		bool	[$clean]	- Set TRUE to cleanup unused variables from template (default behavior).
1817*	@param		string	[$wrap]		- Brackets pair to use on vairables. '{}' by default. Use '[]' for bb codes.
1818*
1819*	@return		string			- Parsed template.
1820*
1821\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
1822function parseVariables ($str, $vars, $clean, $wrap) {
1823
1824	// Using {vars} by default
1825	$wrap = $wrap || '{}';
1826
1827	// Nothing to do if string is empty
1828	if ( !$str )
1829		return $str;
1830
1831	if ( isUndefined($clean) )
1832		$clean = true;
1833
1834	// Preparing wrap pairs
1835	// Assuming 2 char pair like '{}' or '[]'
1836	if ( $wrap.length != 2 )
1837		throw('Invalid var wrapper');
1838
1839	// Preparing 2 wrap variants: normal and escaped one
1840	// Oftenly strings end up as url escaped strings, escaped by parsers
1841	// Thus just searching this too
1842	var $l  = $wrap.charAt(0);
1843	var $r  = $wrap.charAt(1);
1844	var $xl = '%' + $wrap.charCodeAt(0).toString(16).toUpperCase();
1845	var $xr = '%' + $wrap.charCodeAt(1).toString(16).toUpperCase();
1846
1847	// Looping though all vars and replacing given variables
1848	for ( var $i in $vars ) {
1849
1850		// Preparing value separately, in case need to modify something about it
1851		var $value	= $vars[$i];
1852
1853		// Can display simple arrays as lists
1854		if ( isArray($value) )
1855			$value = $value.join(',');
1856
1857		// Skipping anything that can't be placed on template
1858		if ( !isStr($value) && !isNumber($value) )
1859			continue;
1860
1861		// Searching both vars variants
1862		$str = $str.replace( new RegExp( ($l + $i + $r).escape(), 'ig'), $value);
1863		$str = $str.replace( new RegExp( ($xl + $i + $xr).escape(), 'ig'), $value);
1864
1865	} //FOR each var
1866
1867	if ( $clean ) {
1868
1869		// Now cleaning unused, both normal and escaped
1870		$str = $str.replace( new RegExp( $l.escape() + '[\\w\\.-]+' + $r.escape(), 'ig'), '');
1871		$str = $str.replace( new RegExp( $xl.escape() + '[\\w\\.-]+' + $xr.escape(), 'ig'), '');
1872
1873	} //IF autoClean
1874
1875	return $str;
1876
1877} //FUNC parseVariables
1878
1879/** //** ----= arrayToTemplate	=--------------------------------------------------------------------------------------\**//** \
1880*
1881*	Parses {varables} in a template. PHP counterpart alias to parseVariables.
1882*
1883*	@param		object	$vars		- Data object with variable to parse.
1884*	@param		string	$str		- Template to parse.
1885*	@param		bool	[$clean]	- Set TRUE to cleanup unused variables from template (default behavior).
1886*	@param		string	[$wrap]		- Brackets pair to use on vairables. '{}' by default. Use '[]' for bb codes.
1887*
1888*	@return		string			- Parsed template.
1889*
1890\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
1891function arrayToTemplate ($vars, $str, $clean, $wrap) { return parseVariables($str, $vars, $clean, $wrap); }
1892
1893/*--------------------------------------------------------------------------------*\
1894|	isNumeric
1895|----------------------------------------------------------------------------------
1896| Simple function for checking if given string numnber.
1897| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1898|	Params:
1899|		value	string	- Value to check.
1900|	Return:
1901|			bool	- Check status.
1902\*--------------------------------------------------------------= by Mr.V!T =-----*/
1903function isNumeric (value) {
1904
1905	// Numerics are numeric o_O
1906	if ( typeof(value) == 'number' )
1907		return true;
1908
1909	return (value - 0) == value && value.length > 0;
1910} //FUNC isNumeric
1911
1912/*--------------------------------------------------------------------------------*\
1913|	isEmail
1914|----------------------------------------------------------------------------------
1915| Simple function for checking if given string is correct mail.
1916| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1917|	Params:
1918|		value	string	- Value to check.
1919|	Return:
1920|			bool	- Check status.
1921\*--------------------------------------------------------------= by Mr.V!T =-----*/
1922function isEmail (value) {
1923	var filter = /^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9_\-]+\.)+[a-z]{2,6}$/i;
1924	return filter.test(value);
1925} //FUNC isEmail
1926
1927jQuery.fn.findExclude = function($selector, $exclude, $res){
1928
1929	$res = $res || new jQuery();
1930
1931	// Looping through children, saving matching ones,
1932	// and recursively traversing deeper in each
1933	// Skipping ones that match exclusions ofc
1934	this.children().each( function() {
1935
1936		var $el = jQuery(this);
1937
1938		// Checking self to be saved in result
1939		if ( $el.is($selector) )
1940			$res.push(this);
1941
1942		// Traversing deeper if allowed
1943		if( !$el.is($exclude) )
1944			$el.findExclude($selector, $exclude, $res);
1945	}); //jQuery each children
1946
1947	return $res;
1948} //FUNC findExclude
1949
1950/** //** ----= jQuery.align	 =-----------------------------------------\**//** \
1951*
1952* 	Aligns selected element with another element or browser window.
1953*
1954*	@param	string	align	- Align type.
1955*	@param	object	target	- Element to align with.
1956*	@param	bool	fit	- Set TRUE to fit inside element (forced if no target)
1957*
1958*	@return	jQuery		- Aligned element.
1959*
1960\*--------------------------------------------------------------= by Mr.V!T =-----*/
1961jQuery.fn.align = function (align, target, fit, fixed) {
1962
1963// ---- Preparing environment
1964
1965	// Default align is center
1966	if ( align == 'center' ) align = false;
1967	align = align || 'center-center';
1968
1969	align = align.split('-');
1970
1971	if ( fit === undefined ) fit = false;
1972
1973	if ( !target ) fit = true;
1974
1975	// If no target - we will use screen dimensions
1976	if ( !target )
1977		var screen = screenSize();
1978
1979	// Target element dimensions
1980	var tDim = {
1981		width		: ( target )? target.outerWidth() : screen.width,
1982		height		: ( target )? target.outerHeight() : screen.height
1983	}; //OBJECT elDim
1984
1985// ---- Little complicated logic goes next, no comments there - hard to explain :)
1986
1987	var bases = {
1988		'left'		: 0,
1989		'top'		: 0,
1990		'center'	: 0.5,
1991		'right'		: 1,
1992		'bottom'	: 1
1993	} //OBJ bases
1994
1995	var ly = false;
1996
1997	if ( align[0] == 'center' )
1998		align = align.reverse();
1999
2000	if ( ['left', 'right'].indexOf(align[1]) !== -1 ) {
2001		ly = true;
2002		align = align.reverse();
2003	} //IF
2004
2005	if ( ['top', 'bottom'].indexOf(align[0]) !== -1 ) {
2006		ly = true;
2007		align = align.reverse();
2008	} //IF
2009
2010	// Sub function to process aligment separately for each dimension
2011	// Using sub func to avoid copy/paste
2012	function _alignDim (t, l, s, e) {
2013
2014		if ( fit ) l = false;
2015
2016		var d = ds = bases[t];
2017
2018		if ( l && ds != 0.5 )
2019			ds = ( ds )? 0 : 1;
2020
2021		return e * d - s * ds;
2022
2023	} //FUNC _alignDim
2024
2025// ---- Result CSS ----
2026
2027	// preCompiling css
2028	var css = {
2029		'left'	: _alignDim( align[0], !ly, this.outerWidth(true), tDim.width ),
2030		'top'	: _alignDim( align[1], ly, this.outerHeight(true), tDim.height )
2031	} //OBJECT css
2032
2033	// Correcting position, relating to target
2034	if ( target ) {
2035		var pos = (fixed) ? target.offset() : target.position();
2036
2037		css.left += pos.left;
2038		css.top += pos.top;
2039	} //IF target set
2040
2041	this.css(css);
2042
2043	return this;
2044} //FUNC align
2045
2046/*--------------------------------------------------------------------------------*\
2047|	centerWindow
2048|----------------------------------------------------------------------------------
2049| Adds function to jQuery for centering windows
2050| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2051|	Params:
2052|		NONE
2053|	Return:
2054|		SELF
2055\*--------------------------------------------------------------= by Mr.V!T =-----*/
2056jQuery.fn.centerWindow = function () {
2057
2058	var wnd_width	= this.width();
2059	var wnd_height	= this.height();
2060
2061	var screen	= screenSize();
2062
2063	var wnd_left	= ( screen.width - wnd_width ) / 2;
2064	var wnd_top	= ( screen.height - wnd_height ) / 2;
2065
2066	var css		= {'top' : wnd_top, 'left' : wnd_left};
2067
2068	this.css(css);
2069
2070	return this;
2071} //FUNC centerWindow
2072
2073jQuery.fn.maxWidth = function ($outer, $margins) {
2074	var $max = 0;
2075	this.each( function() {
2076		$max = Math.max($max, $outer ? jQuery(this).outerWidth($margins) : jQuery(this).width() );
2077	}); //FUNC each in result
2078	return $max;
2079} //FUNC maxWidth
2080
2081jQuery.fn.maxHeight = function ($outer, $margins) {
2082	var $max = 0;
2083	this.each( function() {
2084		$max = Math.max($max, $outer ? jQuery(this).outerHeight($margins) : jQuery(this).height() );
2085	}); //FUNC each in result
2086	return $max;
2087} //FUNC maxHeight
2088
2089jQuery.fn.screenOffset = function () {
2090
2091	var $pos = this.offset();
2092
2093//	var $top = jQuery('html, body').scrollTop();
2094	var $top = jQuery(window).scrollTop();
2095
2096	$pos.top -= $top;
2097
2098	return $pos;
2099} //FUNC screenOffset
2100
2101jQuery.fn.wrapAround = function ($target) {
2102
2103	// Wrapping assumes border and padding to be same around, so checking only top ones
2104	var $border	= parseInt( this.css('border-top-width') );
2105	var $padding	= parseInt( this.css('padding-top') );
2106
2107	// Supporting direct coordinates input as 4 items array: [left, top, width, height]
2108	if ( isArray($target) ) {
2109
2110		// In array mode coords are given directly
2111		var $css = {
2112			'left'	: $target[0] - $border - $padding,
2113			'top'	: $target[1] - $border - $padding,
2114			'width'	: $target[2],
2115			'height': $target[3]
2116		}; //OBJECT $css
2117
2118	} else { //If dimensions given
2119
2120		if ( !$target.length )
2121			return this;
2122
2123		// Initial values, huge top/left and small width/height
2124		var $x = 10000;
2125		var $y = 10000;
2126
2127		var $toX = 0;
2128		var $toY = 0;
2129
2130		// Looking through all elmements and searching for ourter max dimensions
2131		$target.each( function () {
2132
2133			var $el = jQuery(this);
2134
2135			// Not counting invisible elements
2136			if ( !$el.is(':visible') )
2137				return;
2138
2139			// Getting offset and calculating tox/toy for element
2140			// Then comparing this to found ones already
2141			var $o	= $el.screenOffset();
2142
2143			var $tx = $o.left	+ $el.outerWidth();
2144			var $ty = $o.top	+ $el.outerHeight();
2145
2146			if ( $o.left < $x ) $x = $o.left;
2147			if ( $o.top < $y ) $y = $o.top;
2148			if ( $toX < $tx ) $toX = $tx;
2149			if ( $toY < $ty ) $toY = $ty;
2150
2151		}); //FUNC jQuery.each
2152
2153		// Now we can build helper box
2154		var $css = {
2155			'left'	: $x - $border - $padding,
2156			'top'	: $y - $border - $padding,
2157			'width'	: $toX - $x,
2158			'height': $toY - $y
2159		}; //OBJECT $css
2160
2161	} //IF jQuery
2162
2163	// And apply it to self
2164	this.css($css);
2165
2166	// Continuing chain
2167	return this;
2168} //FUNC wrapAround
2169
2170jQuery.fn.hoverClass = function ($class, $allSet) {
2171
2172	var $this = this;
2173
2174	// Binding with namespaces, using class as namespace
2175	var $ns		= $class.replace(/\W+/g, '');
2176	var $enter	= 'mouseenter.hoverClass.' + $ns;
2177	var $leave	= 'mouseleave.hoverClass.' + $ns;
2178
2179	this.off($enter);
2180	this.off($leave);
2181
2182	// Adding class on enter to whole set, or only one hoverred
2183	this.on($enter, function ($e) {
2184		if ( $allSet )
2185			$this.addClass($class);
2186		else
2187			jQuery(this).addClass($class);
2188	}); //FUNC onMouseenter
2189
2190	this.on($leave, function ($e) {
2191		if ( $allSet )
2192			$this.removeClass($class);
2193		else
2194			jQuery(this).removeClass($class);
2195	}); //FUNC onMouseenter
2196
2197	return this;
2198} //FUNC hoverClass
2199
2200jQuery.fn.groupBy = function ($attribute) {
2201
2202	// Defaulting to data-group attribute.
2203	$attribute = $attribute || 'data-group';
2204
2205	var $res = {}; // Will store groups here
2206
2207	// Looping through each element, and storing as groups
2208	this.each( function () {
2209
2210		var $el = jQuery(this);
2211
2212		// Getting groups attribute
2213		var $attr = $el.attr($attribute);
2214
2215		// Nothing to do if no attribute set (ungrouped element)
2216		if ( !$attr )
2217			return;
2218
2219		// Parsing into groups, allowing common delimiters
2220		var $groups = strToArray($attr, ',.|');
2221
2222		// Assigning element into each group, adding into existing, or creating new ones
2223		for ( var $i in $groups ) {
2224			var $group = $groups[$i];
2225
2226			if ( !$res[$group] )
2227				$res[$group] = $el;
2228			else
2229				$res[$group] = $res[$group].add($el);
2230
2231		} //FOR each group
2232
2233	}); //FUNC each.result
2234
2235	// Returning results
2236	return $res;
2237} //FUNC groupBy
2238
2239function centerWindow (el) {
2240	jQuery(el).centerWindow();
2241} //FUNC centerWindow
2242
2243/*--------------------------------------------------------------------------------*\
2244|	jqmShowCSS
2245|----------------------------------------------------------------------------------
2246| Apllies given css to jQM window and shows it.
2247| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2248|	Params:
2249|		selector	string	- Window to show.
2250|		css		string	- Object with css to apply.
2251|		effect		string	- Effect to use on displaying.
2252|	Return:
2253|				bool	- Alwyas false.
2254\*--------------------------------------------------------------= by Mr.V!T =-----*/
2255function jqmShowCSS (selector, css, effect) {
2256
2257	jQuery(selector).css(css);
2258
2259	if ( jqmVisible(selector) ) return false;
2260
2261	if ( !isJQM(selector) ) {
2262
2263		var opt = {};
2264
2265		if ( effect == 'fade' )
2266			opt = {
2267				onShow: function(h) {
2268					h.w.fadeIn(300);
2269				},
2270				onHide: function(h) {
2271					h.w.fadeOut(300);
2272					h.o.remove();
2273				}
2274			}; //Object o
2275
2276		jQuery(selector).jqm(opt);
2277		if ( jQuery().jqDrag ) jQuery(selector).jqDrag('.jqmHeader');
2278		if ( jQuery().jqResize ) jQuery(selector).jqResize('.jqmResize');
2279	} //IF element is not jqm window already
2280
2281	jQuery(selector).jqmShow();
2282
2283	return false;
2284
2285} //FUNC jqmShowCSS
2286
2287/*--------------------------------------------------------------------------------*\
2288|	jqmShowCentered
2289|----------------------------------------------------------------------------------
2290| Fixes coordinates of jQM window to match center.
2291| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2292|	Params:
2293|		selector	string	- Window to show.
2294|		effect		string	- Effect to use on displaying.
2295|	Return:
2296|				bool	- Alwyas false.
2297\*--------------------------------------------------------------= by Mr.V!T =-----*/
2298function jqmShowCentered (selector, effect) {
2299/**/
2300	var wnd_width	= jQuery(selector).width();
2301	var wnd_height	= jQuery(selector).height();
2302
2303	var parent_window = screenSize();
2304
2305	var wnd_left = ( parent_window.width - wnd_width ) / 2;
2306	var wnd_top = ( parent_window.height - wnd_height ) / 2;
2307
2308	var new_css = {'top':wnd_top,'left':wnd_left};
2309/*/
2310	var new_css = {'top':0,'left':0, 'margin': 'auto auto'};
2311
2312/**/
2313	return jqmShowCSS(selector, new_css, effect);
2314} //FUNC jqmShowCentered
2315
2316/*--------------------------------------------------------------------------------*\
2317|	jqmShowDocked
2318|----------------------------------------------------------------------------------
2319| Fixes coordinates of jQM window to dock to given element.
2320| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2321|	Params:
2322|		selector	string	- Window to show.
2323|		dock_to		string	- Selector of element to dock to.
2324|		effect		string	- Effect to use on displaying.
2325|	Return:
2326|				bool	- Alwyas false.
2327\*--------------------------------------------------------------= by Mr.V!T =-----*/
2328function jqmShowDocked (selector, dock_to, effect) {
2329
2330	var offset	= jQuery(dock_to).offset();
2331	if ( !offset.top ) return false;
2332
2333	var outer	= jQuery(dock_to).outerHeight();
2334
2335	var new_css = {
2336		'top'		: offset.top + outer + 3,
2337		'left'		: offset.left
2338	}; //New CSS
2339
2340	return jqmShowCSS(selector, new_css, effect);
2341} //FUNC jqmShowDocked
2342
2343/*--------------------------------------------------------------------------------*\
2344|	jqmHide
2345|----------------------------------------------------------------------------------
2346| Hides JQM window.
2347| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2348|	Params:
2349|		selector	string	- Window to hide.
2350|		effect		string	- Effect to use on hiding.
2351|	Return:
2352|				bool	- Alwyas false.
2353\*--------------------------------------------------------------= by Mr.V!T =-----*/
2354function jqmHide (selector, effect) {
2355	jQuery(selector).jqmHide();
2356	return false;
2357} //FUNC jqmHide
2358
2359/*--------------------------------------------------------------------------------*\
2360|	isJQM
2361|----------------------------------------------------------------------------------
2362| Check if element is already jqModal window.
2363| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2364|	Params:
2365|		selector	string	- Element to check.
2366|	Return:
2367|		NULL
2368\*--------------------------------------------------------------= by Mr.V!T =-----*/
2369function isJQM (selector) {
2370
2371	var tmp = jQuery(selector).attr('class');
2372	if ( tmp.indexOf('jqmID') < 0 ) return false;
2373
2374	return true;
2375
2376} //FUNC isJQM
2377
2378/*--------------------------------------------------------------------------------*\
2379|	jqmVisible
2380|----------------------------------------------------------------------------------
2381| Checks if jqm window is visible.
2382| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2383|	Params:
2384|		selector	string	- Element to check.
2385|	Return:
2386|		NULL
2387\*--------------------------------------------------------------= by Mr.V!T =-----*/
2388function jqmVisible (element) {
2389
2390	if ( !(element instanceof jQuery) )
2391		element = jQuery(element);
2392
2393	var disp = element.css('display');
2394
2395	return (disp != 'none');
2396} //FUNC jqmVisible
2397
2398function centerWindow (win) {
2399	var wnd_width	= jQuery('#'+win).width();
2400	var wnd_height	= jQuery('#'+win).height();
2401
2402	var parent_window = screenSize();
2403
2404	var wnd_left = ( parent_window.width - wnd_width ) / 2;
2405	var wnd_top = ( parent_window.height - wnd_height ) / 2;
2406
2407	var new_css = {'top':wnd_top,'left':wnd_left};
2408	jQuery('#'+win).css(new_css);
2409} //FUNC
2410
2411function getOuterHTML (el) {
2412
2413	if ( el.outerHTML ) return el.outerHTML;
2414
2415	var tmp = document.createElement(el.parentNode.tagName);
2416	tmp.appendChild(el.cloneNode(true));
2417
2418	return tmp.innerHTML;
2419} //FUNC getOuterHTML
2420
2421function strToElement (html) {
2422	var tmp = document.createElement('div');
2423	tmp.innerHTML = html;
2424
2425	return tmp.firstChild;
2426} //FUNC strToElement
2427
2428function setOuterHTML (el, html) {
2429
2430	if ( el.outerHTML ) return el.outerHTML = html;
2431
2432	var n = strToElement(html);
2433
2434	el.parentNode.replaceChild(n, el);
2435} //FUNC setOuterHTML
2436
2437/** //** ----= formToArray	=--------------------------------------------------------------------------------------\**//** \
2438*
2439*	Collects input values as data object. Result is exactly same as one you get with $_POST.
2440*	Supports nested arrays and sets in naming. E.g.: name="lvl1[lvl2][lvl3][]"
2441*
2442*	@param		object(HTMLFormElement)
2443*					$form	- Source form.
2444*
2445*	@return		object			- Data collected from form.
2446*
2447\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
2448function formToArray ($form, $options) {
2449
2450	// Storing results in object
2451	var $data = {};
2452
2453	// Defaulting options
2454	$options = $options || {};
2455
2456// ---- 3rd parties ----
2457
2458	// If there is tiny - forcing it to save editors
2459	if ( typeof(tinyMCE) != 'undefined' )
2460		tinyMCE.triggerSave();
2461
2462	// Optionally supporting jQuery elements, though shold point exactly to form
2463	if ( isJQ($form) ) {
2464
2465		// Not proceesing if not form though
2466		if ( !$form.is('form') )
2467			return $data;
2468
2469		// Getting DOM from jQuery
2470		$form = $form.get(0);
2471	} //IF jQuery given
2472
2473// ---- Form ----
2474
2475	// Counting inputs with same name for sets resolving
2476	var $index = {};
2477
2478	// Looping through elements and getting values for each
2479	for ( var $i = 0; $i < $form.elements.length; $i++ ) {
2480
2481	// ---- Element ----
2482
2483		// Getting element to work with
2484		var $el		= $form.elements.item($i);
2485
2486		// Collecting value, and then storing it in data object
2487		var $val;
2488
2489		// Skipping it if it does not have name
2490		if ( !$el.name )
2491			continue;
2492
2493	// ---- Input ----
2494
2495		switch ( $el.type ) {
2496			case 'file' :
2497				// In HTML files are not included in post
2498				continue;
2499
2500			case 'radio' :
2501			case 'checkbox'	:
2502
2503				$val = $el.value;
2504
2505				if ( $val == 'on' ) {
2506
2507					// Using slightly alternate behavior
2508					// where checkboxes without values (val == on) return 1/0 instead of 1/unset
2509					$val = ( $el.checked )? 1 : 0;
2510
2511				} //IF no value
2512				else if ( !$el.checked ) {
2513
2514					if ( $options['emptyChecks'] ) {
2515
2516						$val = '';
2517
2518					} //IF empty checkboxes should present
2519
2520					else {
2521
2522						// For valued checkboxes - regular behavior
2523						continue;
2524
2525					} //IF standard behavior
2526
2527				} //IF value is set
2528
2529				break;
2530
2531			case 'select-one' :
2532
2533				// Using dedicated tool
2534				$val = getValue_Select($el);
2535
2536				break;
2537
2538			case 'select-multiple' :
2539
2540				// Using dedicated tool
2541				$val = getValue_MutliSelect($el);
2542
2543				break;
2544
2545			default	:
2546
2547				// Regular inputs have just value
2548				$val = $el.value;
2549		} //SWITCH
2550
2551		// Nothing to do with null
2552		if ( isUndefined($val) )
2553			continue;
2554
2555	// ---- Data ----
2556
2557		var $name	= $el.name;	// That will be working name
2558
2559		// Expecting array to happen, so parsing as path right away
2560		var $path	= regexMatchAll(/[\w\-]+/g, $name);
2561
2562		// Problematic paths are skipped too
2563		if ( !$path[0] )
2564			continue;
2565
2566		// Full match is all we need
2567		$path = $path[0];
2568
2569		// Indexing now, as it looks like valid name
2570		$index[$name]	= isSet($index[$name]) ? ++$index[$name] : 0;
2571
2572		// Special case for sets
2573		// Those should be stored as simple array
2574		// Exception for multiarrays: those always have [] to work properly
2575		// (except rare cases when multiple same named selects used... which is never... currently only one will be allowed)
2576
2577		if ( ($el.type != 'select-multiple') && $name.endsWith('[]') ) {
2578
2579			// Need to merge with existing array if one is present
2580			var $set = arrayPath($data, $path);
2581
2582			// Merging value into set, which will be set into data
2583
2584			if ( isObject($set, true) )
2585
2586				// Adding into objectx using index
2587				$set[$index[$name]] = $val;
2588
2589			else if ( isArray($set) )
2590
2591				// Pushing if array
2592				$set.push($val)
2593
2594			else
2595				// Non arrays are overwritten
2596				$set = [$val];
2597
2598			// Preparing to be set back to data
2599			$val = $set;
2600
2601		} //IF set given
2602
2603		// Now we have both value and path
2604		// Just setting it
2605		arrayPath($data, $path, $val);
2606
2607	} //FOR each element
2608
2609	return $data;
2610} //FUNC formToArray
2611
2612/** //** ----= formFromArray	=--------------------------------------------------------------------------------------\**//** \
2613*
2614*	Sets form inputs values from given data object.
2615*	Supports arrays and sets in elements names and tinyMCE Editor if applied to textarea.
2616*
2617*	@param		object(HTMLFormElement)
2618*					$form	- Form to setup.
2619*
2620*	@param		object		$source	- Values to set.
2621*
2622\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
2623function formFromArray ($form, $source) {
2624
2625	// Resaving to do not break source
2626	var $data	= jQuery.extend({}, $source);
2627
2628	// Counting inputs with same name for sets resolving
2629	var $index = {};
2630
2631// ---- Form ----
2632
2633	for ( var $i = 0; $i < $form.elements.length; $i++ ) {
2634
2635	// ---- Element ----
2636
2637		// Getting form element, it's name and value that should be applied
2638		var $el		= $form.elements.item($i);
2639
2640		// Skipping it if it does not have name
2641		if ( !$el.name )
2642			continue;
2643
2644		// Getting element name
2645		var $name	= $el.name;
2646
2647		// Expecting array to happen, so parsing as path right away
2648		var $path	= regexMatchAll(/[\w\-]+/g, $name);
2649
2650		// Problematic paths are skipped too
2651		if ( !$path[0] )
2652			continue;
2653
2654		// Full match is all we need
2655		$path = $path[0];
2656
2657		// Indexing now, as it looks like valid name
2658		$index[$name]	= isSet($index[$name]) ? ++$index[$name] : 0;
2659
2660	// ---- Value ----
2661
2662		var $val = arrayPath($data, $path);
2663
2664		// Resolving set
2665		var $set = $val;
2666		if ( $set && $name.endsWith('[]') ) {
2667
2668			// Getting value by index
2669			$val = $set[$index[$name]];
2670
2671		} //IF set given
2672
2673		// Making sure value is valid after all
2674		$val = ( isUndefined($val) || $val === false || $val === null ) ? '' : $val;
2675
2676		// Special case for date inputs
2677		if ( $val == '0000-00-00' || $val == '0000-00-00 00:00:00' )
2678			$val = '';
2679
2680	// ---- Inputs ----
2681
2682		switch ($el.type) {
2683
2684			case 'checkbox'	:
2685			case 'radio'	:
2686
2687				// For simple checkboxes - comparing against found value
2688				// Value will be either set directly or indexed in set
2689				if ( $el.value == 'on' ) {
2690
2691					$el.checked = ( !isEmpty($val) );
2692					break;
2693
2694				} //IF simple checkbox
2695
2696				// If not part of set - just checking values to match
2697				// Casting incoming value to string manually to ensure that match is correct for numbers
2698				// Input value is always string anyway
2699				if ( !isObject($set, true) ) {
2700
2701					$el.checked = ( $val.toString() === $el.value );
2702					break;
2703
2704				} //IF not a set
2705
2706				// Custom behavior if part of set - checking by value presense
2707				// Looping through and checking if value is there
2708				// Doing manually instead of array's indexOf cuz assoc array or object could happen
2709				var $tmp = false;
2710				for ( var $t in $set )
2711					if ( $t in $set && $set[$t].toString() === $el.value )
2712						$tmp = true;
2713
2714				$el.checked = $tmp;
2715
2716				break;
2717
2718			case 'select-one'	:
2719			case 'select-multiple'	:
2720
2721				// Using entire set
2722				setValue_Select($el, $set);
2723
2724				break;
2725
2726			case 'file' :
2727
2728				// File just resetting to default.
2729				// Files can't have values, unless selected
2730				// So if we're setting form from array - it better have no value than old some
2731				$el.value	= '';
2732
2733				// Alternatively - can recreate input completely
2734				// Getting input HTML, then creating new element from it,
2735				// Doing this way since simple clone will not help
2736			//	var $html = getOuterHTML($el);
2737			//	setOuterHTML($el, $html);
2738
2739				// Skipping styled forms
2740				// ToDo: capture events instead
2741
2742				// Special case for morweb inputs - those are not recreated
2743				// And values are handled differently
2744				// ToDo: remove morweb hardcode and allow custom inputs handling
2745				if ( $el.className.indexOf('mw') !== -1 ) {
2746
2747					// Adding as dedicated attribute, which will be handled by morweb later on
2748					var $jFile	= jQuery($el);
2749					$jFile.attr('data-file', $val || '');
2750
2751					// Also setting value
2752
2753					// Triggering change
2754					$jFile.change();
2755
2756				} //IF morweb input
2757
2758				break;
2759
2760			case 'textarea'	:
2761
2762				// Checking if textarea can be tinyMCE
2763				if ( $el.style.display == 'none' && ( typeof tinyMCE != 'undefined' ) ) {
2764
2765					// Checking if tiny really applied to it
2766					var $tiny = tinyMCE.get($el.id);
2767
2768					// If it's tiny - setting values into it too.
2769					if ( $tiny )
2770						$tiny.setContent($val);
2771
2772				}; //IF hidden and tinyMCE exists
2773
2774				$el.value = $val;
2775
2776				break;
2777
2778			case 'button' :
2779			case 'submit' :
2780
2781				break;
2782
2783			default	:
2784				$el.value = $val;
2785
2786		} //SWITCH
2787
2788		if ( isSet(jQuery) ) {
2789
2790			// Triggering onChange in case if some set.
2791			jQuery($el).change();
2792
2793			// Additionally triggering custom "setup" event.
2794			// This helps to distinguish between regular updates (caused by other code) and whole form setup
2795			jQuery($el).trigger('setup');
2796
2797		} //IF jQuery present
2798
2799	} //FOR each element
2800
2801} //FUNC formFromArray
2802
2803/** //** ----= jQuery.asArray	=--------------------------------------------------------------------------------------\**//** \
2804*
2805* 	Simple jQuery wrapper for formToArray() function.
2806*
2807*	@return	array	- Form elements valus as array.
2808*
2809\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
2810jQuery.fn.asArray = function ($options) {
2811
2812	if ( !this.is('FORM') ) return {};
2813
2814	return formToArray(this.get(0), $options);
2815
2816} //FUNC asArray
2817
2818/** //** ----= jQuery.fromArray	=--------------------------------------------------------------------------------------\**//** \
2819*
2820* 	Simple jQuery wrapper for formFromArray() function.
2821*
2822*	@param	object	data	- Array with values to set to elements.
2823*	@return	jQuery		- jQuery object for chain calls.
2824*
2825\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
2826jQuery.fn.fromArray = function (data) {
2827
2828	if ( !this.is('FORM') ) return this;
2829
2830	formFromArray( this.get(0), data );
2831
2832	return this;
2833
2834} //FUNC fromArray
2835
2836/*--------------------------------------------------------------------------------*\
2837|	getValue_Select
2838|----------------------------------------------------------------------------------
2839| Returns correct value of <select> based in setted or not value attribute. IE FIX.
2840| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2841|	Params:
2842|		element	object	- DOM elemnt to get value.
2843|	Return:
2844|			MIXED
2845|			bool	- FALSE in case of error.
2846|			string	- Element value.
2847\*--------------------------------------------------------------= by Mr.V!T =-----*/
2848function getValue_Select (element) {
2849
2850	if ( element.options.selectedIndex < 0 ) return false;
2851
2852	var option	= element.options[element.options.selectedIndex];
2853	var value	= getValue_Option(option);
2854	//(option.attributes.value && option.attributes.value.specified)? option.value : option.text
2855
2856	return value;
2857} //FUNC getValue_Select
2858
2859/*--------------------------------------------------------------------------------*\
2860|	getValue_MutliSelect
2861|----------------------------------------------------------------------------------
2862| Returns values of <select> with multiple selection enabled as an array.
2863| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2864|	Params:
2865|		element	object	- DOM elemnt to get value.
2866|	Return:
2867|			array	- Array with values. Can be emty.
2868\*--------------------------------------------------------------= by Mr.V!T =-----*/
2869function getValue_MutliSelect (element) {
2870
2871	var res = [] ;
2872
2873	if ( !element.options || element.options.length <= 0 ) return res;
2874
2875	for ( var i = 0; i < element.options.length; i++ ) {
2876
2877		if ( !element.options[i].selected ) continue;
2878
2879		res.push(getValue_Option(element.options[i]));
2880	} //FOR all managers
2881
2882	return res;
2883} //FUNC getValue_MutliSelect
2884
2885/*--------------------------------------------------------------------------------*\
2886|	setValue_Select
2887|----------------------------------------------------------------------------------
2888| Correctly sets value to selector. Works in old IE.
2889| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2890|	Params:
2891|		element	object	- DOM elemnt to set value.
2892|		values	MIXED	- Single string value or array with selected values.
2893|	Return:
2894|			VOID
2895\*--------------------------------------------------------------= by Mr.V!T =-----*/
2896function setValue_Select (element, values) {
2897
2898	if ( element.options.length <= 0 ) return;
2899
2900	if ( !values )
2901		values = [];
2902
2903	if ( typeof(values) != 'object' ) {
2904
2905		// Converting values depending on multiple attribute
2906	 	// If multiple - most likely it's simple array string.
2907		if ( element.multiple || element.size )
2908			values = strToArray(values);
2909		else
2910			// Stringifying value, cuz if integer come - indexOf will ignore it
2911			values = [values+''];
2912
2913	} //IF not array come
2914
2915	for ( var i = 0; i < element.options.length; i++ ) {
2916
2917		var val = getValue_Option(element.options[i]);
2918
2919		element.options[i].selected = (values.indexOf(val) != -1);
2920
2921	} //FOR all elements
2922
2923} //FUNC setValue_Select
2924
2925/*--------------------------------------------------------------------------------*\
2926|	getValue_Option
2927|----------------------------------------------------------------------------------
2928| Returns correct value of <option> based in setted or not value attribute. IE FIX.
2929| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2930|	Params:
2931|		element	object	- DOM elemnt to get value.
2932|	Return:
2933|			string	- Element value.
2934\*--------------------------------------------------------------= by Mr.V!T =-----*/
2935function getValue_Option (element) {
2936	var value	= (element.attributes.value && element.attributes.value.specified)? element.value : element.text;
2937	return value;
2938} //FUNC getValue_Option
2939
2940/*--------------------------------------------------------------------------------*\
2941|	getSelectorOptions
2942|----------------------------------------------------------------------------------
2943| Returns array with selector values.
2944| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2945|	Params:
2946|		element	object	- DOM elemnt to get value.
2947|	Return:
2948|			array	- Selector values.
2949\*--------------------------------------------------------------= by Mr.V!T =-----*/
2950function getSelectorOptions (element) {
2951
2952	var res = [] ;
2953
2954	if ( !element.options || element.options.length <= 0 ) return res;
2955
2956	for ( var i = 0; i < element.options.length; i++ ) {
2957
2958		var option = element.options[i];
2959
2960		if ( option.attributes.value && option.attributes.value.specified ) {
2961			res[option.value] = option.text;
2962		} else { //IF value set
2963			res.push(option.text);
2964		} //IF value not set
2965
2966	} //FOR each option
2967
2968	return res;
2969} //FUNC getSelectorOptions
2970
2971/** //** ----= strToArray		 =--------------------------------------\**//** \
2972*
2973* 	Splits string into array with given delimeters, trimming resulting items.
2974*
2975* 	@param	string	str	- String to split.
2976*	@return	array		- Resulting array.
2977*
2978\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
2979function strToArray(str, delim) {
2980
2981	// No need to split if already array
2982	if ( isArray(str) )
2983		return str;
2984
2985	delim = delim || ',|';
2986
2987	var tmp = str.split( new RegExp('\\s*[' + delim + ']\\s*') );
2988
2989	var res = [];
2990
2991	// Skipping empties
2992	for ( var i in tmp )
2993		if ( tmp[i] ) res.push(tmp[i]);
2994
2995	return res;
2996} //FUNC strToArray
2997
2998/** //** ----= strToObj		 =----------------------------------------------\**//** \
2999*
3000* 	Splits string into object array with given delimeters
3001*
3002* 	@param	string	str	- String to split.
3003*	@return	array		- Resulting array.
3004*
3005\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
3006function strToObj (str, delim, auto_tirm) {
3007
3008	var res	= {};
3009
3010	if ( !str )
3011		return res;
3012
3013	var tmp = str.split(delim);
3014
3015	var j = 0;
3016
3017	for ( var i in tmp ) {
3018
3019		var pos = tmp[i].indexOf('=');
3020
3021		if ( pos != -1 ) {
3022			var key = tmp[i].substr(0, pos);
3023			var val = tmp[i].substr(pos+1);
3024		} else { //IF eq symbol found
3025			var key = j+'';
3026			var val = tmp[i];
3027		} //IF single value
3028
3029		key = key.trim();
3030
3031		if ( auto_tirm )
3032			val = val.trim();
3033
3034		res[key] = val;
3035
3036		j++;
3037
3038	} //FOR each value
3039
3040	return res;
3041} //FUNC strToObj
3042
3043/** //** ----= cb			 =--------------------------------------\**//** \
3044*
3045* 	Callback runner helper. Used to simplify code. Checks if funciton given.
3046*
3047* 	@param	function	func	- Function to run.
3048*	@param	MIXED		*	- All next parameters will be passed to function.
3049*
3050*	@return	MIXED			- Funciton restult.
3051*
3052\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
3053function cb(func, args) {
3054
3055	// ToDo: apply is not applicable here, so think better way;
3056
3057} //FUNC cb
3058
3059/** //** ----= checkAll			 =--------------------------------------\**//** \
3060*
3061* 	Sets value to all checkboxes in an element.
3062*
3063* 	@param	bool	value	- Checkbox state.
3064* 	@param	string	element	- jQuery selector.
3065*	@return	bool		- Initial value.
3066*
3067\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
3068function checkAll (value, element) {
3069
3070	jQuery(element).find('INPUT[type=checkbox]').attr('checked', value);
3071
3072	return false;
3073} //FUNC checkAll
3074
3075function ToggleDisplay(elementID, state) {
3076	element = document.getElementById(elementID);
3077
3078	if ( !element ) return;
3079
3080	if (state == undefined) {
3081		state = ( element.style.display == 'none' );
3082	} //IF no state specified
3083
3084	element.style.display = state ? 'inline' : 'none';
3085} //FUNC ToggleDisplay
3086
3087function screenSize() {
3088    var w, h;
3089    w = (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth));
3090    h = (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight));
3091    return {width:w, height:h};
3092}
3093
3094function selectRow(row, state) {
3095	var row_class =	jQuery('#'+row).attr('class');
3096	row_class = row_class.replace('_selected','');
3097	row_class += ( state )? '_selected' : '';
3098	jQuery('#'+row).attr('class', row_class);
3099} //FUNC selectRow
3100
3101/*/
3102function insert_bar (bar_place) {
3103	jQuery('#'+bar_place).html('<IMG src="/images/processing/bar.gif" alt="Loading...">');
3104} //FUNC insert_bar
3105
3106function insert_green_bar (bar_place) {
3107	jQuery('#'+bar_place).html('<IMG src="/images/processing/bar_green.gif" alt="Loading...">');
3108} //FUNC insert_bar
3109//*/
3110
3111/** //** ----= getCookie		 =--------------------------------------\**//** \
3112*
3113* 	Returns cookie with given name.
3114*
3115* 	@param	string	name	- Cookie name to search.
3116*	@param	string	[def]	- Default value to return if cookie not found.
3117*
3118*	@return	string		- Cookie value.
3119*
3120\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
3121function getCookie (name, def) {
3122
3123	if ( def == undefined ) def = '';
3124
3125	var cookieValue	= def;
3126	var cookieName	= name + '=';
3127
3128	if ( document.cookie.length > 0 ) {
3129
3130		offset = document.cookie.lastIndexOf(cookieName);
3131		if ( offset != -1 ) {
3132
3133			offset	+= cookieName.length;
3134
3135			end	= document.cookie.indexOf(';', offset);
3136			if (end == -1) end = document.cookie.length;
3137
3138			cookieValue = unescape(document.cookie.substring(offset, end))
3139
3140		} //IF found smth
3141
3142	} //IF there are cookies
3143
3144	return cookieValue;
3145} //FUNC getCookie
3146
3147/** //** ----= setCookie	 =----------------------------------------------\**//** \
3148*
3149*	Sets cookie with given name.
3150*
3151*	@param	string	name	- Cookie name to set.
3152*	@param	string	value	- Value of cookie.
3153*	@param	string	[hours]	- Expiration date in hours.
3154*
3155\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
3156function setCookie (name, value, hours) {
3157
3158	var expire	= "";
3159
3160	if ( hours ) {
3161		expire = new Date((new Date()).getTime() + hours * 3600000);
3162		expire = "; expires=" + expire.toGMTString();
3163	} //IF there is set expiration
3164
3165	document.cookie = name + "=" + escape(value) + expire + ';path=/;';
3166
3167} //FUNC setCookie
3168
3169function get_controller_views(views) {
3170		insert_bars(views);
3171		insert_views(views,0);
3172} //FUNC get_controller_views
3173
3174function mark_checkboxes(container_form,val) {
3175	for (var i = 0; i < container_form.elements.length; i++) {
3176		el = container_form.elements[i];
3177		if (el.type=='checkbox')
3178			el.checked=val;
3179	}
3180} //FUNC mark_checkboxes
3181
3182function status_string(message,style_class,padding) {
3183	if (message == '') return '';
3184	if (!style_class) style_class = 'status_error';
3185	if (!padding) padding = 0;
3186	return '<div class="'+style_class+'" style="padding:'+padding+'px">'+message+'</div>';
3187} //FUNC error_string
3188
3189function ajax_pack_data(controller_url,place_to_put, data, ajax_options) {
3190	var res = [];
3191	res['controller']	= controller_url;
3192	res['place']		= place_to_put;
3193	if (!data) data	= {};
3194	res['data']		= data;
3195	if (!ajax_options) ajax_options	= {};
3196	res['options']		= ajax_options;
3197	return res;
3198} //FUNC pack_view
3199
3200function ajax_insert_bars(views) {
3201	for (i=0; i < views.length; i++) {
3202		insert_bar(views[i]['place']);
3203	} //FOR each views
3204} //FUNC insert_bars
3205
3206function ajax_insert_views(views,num) {
3207	if (num >= views.length) return false;
3208
3209	var tdata = views[num]['data'];
3210
3211	if (views[num]['options'].onLoad) {views[num]['options'].onLoad(tdata)};
3212	jQuery.ajax({
3213		type	: 'POST', dataType: 'html',
3214		url	: views[num]['controller'],
3215		data	: views[num]['data'],
3216		success	: function(obj){
3217				jQuery('#'+views[num]['place']).html(obj);
3218				ajax_insert_views(views,num+1);
3219				if (views[num]['options'].onSuccess) {views[num]['options'].onSuccess(tdata)};
3220			},//FUNC success
3221		error : function (XMLHttpRequest, textStatus, errorThrown) {
3222				jQuery('#'+views[num]['place']).html(status_string('This section is not avaible now (Possibly under construction). Try again later.'));
3223				ajax_insert_views(views,num+1);
3224			} //FUNC error
3225	}); //ajax
3226}//FUNC insert_views
3227
3228function ajax_get_views(views) {
3229		ajax_insert_bars(views);
3230		ajax_insert_views(views,0);
3231} //FUNC get_controller_views
3232
3233function ajax_get_view(controller_url,place_to_put,data, ajax_options) {
3234	ajax_get_views([ajax_pack_data(controller_url,place_to_put,data, ajax_options)]);
3235} //FUNC get_controller_view
3236
3237function ajax_post (post_form,controller,status_place,settings) {
3238	insert_bar(status_place);
3239	var tt = document.getElementById(post_form);
3240	if (!tt) alert('no form');
3241//*/
3242	jQuery.ajaxUpload ({
3243		type		: 'POST', dataType : 'html',
3244	        url		: controller,
3245	        secureuri	: false,
3246	        uploadform	: document.getElementById(post_form),
3247	        success		: function (res, status) {
3248					data = res.split('<!-- CUT -->');
3249					jQuery('#'+status_place).html(data[0]);
3250
3251					if ((data.length != 1) && (data[1] == 'success') ) {
3252						if (settings.success) settings.success(data);
3253					} else {
3254						if (settings.error) settings.error(data);
3255					} //IF returned status
3256
3257				}, //FUNC sucess
3258		error		: function (res, status) {
3259					alert('error');
3260					jQuery('#'+status_place).html(status_string('Error: '+status));
3261					if (settings.error) settings.error();
3262				} //FUNC error
3263
3264	}); //AJAX
3265//*/
3266} //FUNC ajax_post
3267
3268/** //** ----= getDimensions	=--------------------------------------------------------------------------------------\**//** \
3269*
3270*	Parses strings like '100x200' into [x,y] dimensions pair (with Y being optional).
3271* 	Returns FALSE if string does not contain valid dimensions string.
3272*
3273*	@param		string	$dimensions	- Dimensions string.
3274* 	@param		bool	[$strict]	- Strict validation. Will require Y to present
3275*
3276*	@return		MIXED			- Array with named dimensons or FALSE if failed.
3277*
3278\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
3279function getDimensions ($dimensions, $strict) {
3280
3281	// Nothing to do if notihng fiven
3282	if ( !$dimensions )
3283		return false;
3284
3285	// Simple check for compatability with parsed dimensions, allowing mixed params in callee funcions.
3286	if ( isArray($dimensions) || isObject($dimensions) ) {
3287
3288		// Fast validation for X to be present: it's minimal requirement for valid dimensions array
3289		if ( !isSet($dimensions['x']) )
3290			return false;
3291
3292		// Fast validation for strict mode
3293		if ( $strict && !isSet($dimensions['y']) )
3294			return false;
3295
3296		return $dimensions;
3297	} //IF array given
3298
3299	// Parsing for dimensions, using regex. It also allows to validate dimensions stirng.
3300	// X and Y will be named in matches, which makes it easyer to return.
3301
3302	// Strict option really changes counter for second (x200) match
3303	$strict = $strict ? '+' : '?';
3304
3305	// Capturing groups and then checking once that good
3306	var $reg	= '^([0-9]+)(x([0-9]+))' + $strict + '$';
3307	var $match	= $dimensions.match( new RegExp($reg, 'i') );
3308
3309	// Checking existing  params
3310	if ( !$match )
3311		return false;
3312
3313	// Grabbing only named matches into result (to keep result clear)
3314	var $res = {};
3315
3316	// X always present at this step (othewise we'd returned already)
3317	$res['x']	= $match[1];
3318
3319	// Y is optional
3320	if ( isSet($match[3]) )
3321		$res['y'] = $match[3];
3322
3323	// Can return now
3324	return $res;
3325} //FUNC getDimensions
3326
3327/* #### MATH ################################################################################################################ */
3328
3329/** //** ----= asDeg	=----------------------------------------------------------------------------------------------\**//** \
3330*
3331*	Converts radians to degrees.
3332*
3333*	@param		float	$angle	- Angle in radians.
3334*
3335*	@return		flaot		- Angle in degrees.
3336*
3337\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
3338function asDeg ($angle) {
3339	return $angle * (180 / Math.PI);
3340} //FUNC asDeg
3341
3342/** //** ----= asRad	=----------------------------------------------------------------------------------------------\**//** \
3343*
3344*	Converts degrees to radians.
3345*
3346*	@param		float	$angle	- Angle in degrees.
3347*
3348*	@return		flaot		- Angle in radians.
3349*
3350\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/
3351function asRad ($angle) {
3352	return $angle * (Math.PI / 180);
3353} //FUNC asRad

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.