( function ( $ ) {

	$.fn.hasScrollbar = function() {
		var element = this.get( 0 );
		if ( element.scrollHeight > element.clientHeight ) return true;
	}

	$.fn.hasID  = function( id ) {
		return this.attr( 'id' ) == id;
	}

	$.fn.extend({
		animateStep: function( options ) {
			return this.each( function() {
				var elementOptions = $.extend( {}, options, { step: options.step.bind( $( this ) ) } );
				$( { x: options.from } ).animate( { x: options.to }, elementOptions );
			});
		},
		rotate: function( value ) {
			return this.css( "transform", "rotate(" + value + "deg)" );
		}
	});

	$.fn.isOnScreen = function( partial ) {
		// let's be sure we're checking only one element (in case function is called on set)
		var t = $( this ).first();

		// we're using getBoundingClientRect to get position of element relative to viewport
		// so we dont need to care about scroll position
		var box = t[0].getBoundingClientRect();

		// let's save window size
		var win = {
			h : $( window ).height(),
			w : $( window ).width()
		};

		// firstly we check one axis
		var topEdgeInRange    = box.top >= 0 && box.top <= win.h;
		var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;

		var leftEdgeInRange  = box.left >= 0 && box.left <= win.w;
		var rightEdgeInRange = box.right >= 0 && box.right <= win.w;

		// here we check if element is bigger then window and 'covers' the screen in given axis
		var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
		var coverScreenVertically   = box.top <= 0 && box.bottom >= win.h;

		// now we check 2nd axis
		var topEdgeInScreen    = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
		var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );

		var leftEdgeInScreen  = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
		var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );

		// now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
		var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
		var isEntirelyOnScreen  = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;

		return partial ? isPartiallyOnScreen : isEntirelyOnScreen;

	};

	$.fn.wordHighlight = function ( str, className ) {
		var regex = new RegExp( "\\b" + str + "\\b", "gi" );

		return this.each( function() {
			this.innerHTML = this.innerHTML.replace( regex, function( matched ) {
				return '<span class="' + className + '">' + matched + '</span>';
			});
		});
	};

} ( jQuery ) );

// CHECK IF VAR IS NUMBER
function isNumeric( n ) {
	return ! isNaN( n ) && !/^0x/i.test( n ) && isFinite( n );
}

// CHECK IF VAR IS INT
function isInt( value ) {
	return ! isNaN( value ) && ( function( x ) { return ( x | 0 ) === x; } )( parseFloat( value ) );
}

// PREVENT MULTIPLE CLICKS ON A LINK
function clickAndDisable( link ) {
	link.onclick = function( event ) {
		event.preventDefault();
		jQuery( this ).addClass( 'disabled' );
	}
}

// CHECK IF VAR IS LINK
function is_valid_url( string ) {
	try {
		new URL(string);

		return true;
		
	} catch {
		return false;

	}
}

// CONVERT TEXT TO LINK
function linkify( text ) {
    if ( ! text ) return text;

    const url_regex = /(https?:\/\/[^\s]+)/g;
    return text.replace( url_regex, '<a href="$1" target="_blank">$1</a>' );
}

// GET URL PARAMETER
function getUrlParameter( param ) {
	var pageURL = decodeURIComponent( window.location.search.substring( 1 ) );
	var urlVars = pageURL.split( '&' );
	var paramName;
	var i;

	for ( i = 0; i < urlVars.length; i++ ) {
		paramName = urlVars[i].split( '=' );

		if (paramName[0] === param) {
			return paramName[1] === undefined ? true : paramName[1];
		}
	}
};

// GET URL PARAMETER FROM GIVEN URL ADDRESS
function getParameterFromGivenURL( url, name ) {
	return ( RegExp( name + '=' + '(.+?)(&|$)' ).exec( url ) || [,null] )[1];
}

// GET URL VARS
function getUrlVars(){
	var vars      = [], hash;
	var toreplace = '';
	var thisurl   = window.location.href.split( '#' )[0];
	var hashes    = thisurl.slice( window.location.href.indexOf( '?' ) + 1 ).split( '&' );

	if ( typeof hashes !== 'undefined' ) {

		for ( var i = 0; i < hashes.length; i++ ) {
			hash = hashes[i].split( '=' );
			if ( hash[0] == 'site_currency' ) {
				toreplace = 'site_currency=' + hash[1];
			}
		}

		hashes = hashes.join( '&' );
	} else {
		hashes = '';
	}

	loc = hashes.replace( toreplace, '' );
	loc = loc.replace( wpj_vars.site_URL, '' );
	loc = loc + '&';
	loc = loc.replace( '&&', '&' );

	return loc;
}

// GET JS SAFE DATE FORMAT
function getSafeDateFormat( date, date_type ) {
	var date = new Date( date );

	var yr    = date.getFullYear();
	var month = date.getMonth() < 10 ? '0'.concat( parseInt( date.getMonth() ) + parseInt( 1 ) ) : parseInt( date.getMonth() ) + parseInt( 1 );
	var day   = date.getDate()  < 10 ? '0'.concat( date.getDate() ) : date.getDate();

	var newDate = yr + '-' + day + '-' + month;

	if ( date_type == 'datetime' ) {
		newDate = newDate + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
	} else if ( date_type == 'time' ) {
		newDate = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
	}

	return newDate;
}

// RETURN TRUE IF LOADED IN IFRAME
function inIframe() {
	try {
		return window.self !== window.top;
	} catch (e) {
		return true;
	}
}

// RETURN TRUE IF DEVICE IS MOBILE
function isMobile() {
	var isMobile = false;

	if ( /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test( navigator.userAgent )
		|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( navigator.userAgent.substr( 0,4 ) ) ) {
		isMobile = true;
	}

	return isMobile;
}

// RETURN DEVICE iOS VERSION
function getIOSversion() {
	if ( /iP(hone|od|ad)/.test( navigator.platform ) ) {
		var v = ( navigator.appVersion ).match( /OS (\d+)_(\d+)_?(\d+)?/ );
		return [parseInt( v[1], 10 ), parseInt( v[2], 10 ), parseInt( v[3] || 0, 10 )];
	} else {
		return false;
	}
}

// CHANGE THE CURRENCY OF A NUMBER
function getExchangeValue( amount, from, to ) {
	var from = from.toUpperCase();
	var to   = to.toUpperCase();
	from     = from.trim();
	to       = to.trim();

	var data = null;
	jQuery.ajax({
		async: false,
		url: wpj_vars.ajaxurl,
		data: {
			action : 'exchange_rates_action'
		},
		dataType: "json",
		success: function( response ) {
			data = response;
		}
	});

	if ( ! data ) {
		return false;
	}

	var rate_from, rate_to, dollars;
	jQuery.each( data.rates, function( index, element ) {
		if ( index == from ) {
			rate_from = element;
		}
		if ( index == to ) {
			rate_to = element;
		}
	});

	if ( ! rate_from || !rate_to ) {
		return amount;
	} else if ( from == to ) {
		return amount;
	} else {
		if ( from != 'USD' ) {
			dollars = amount / rate_from;
		} else {
			dollars = amount;
		}

		if ( to != 'USD' ) {
			ret = Math.round( rate_to * dollars, 2 );
		} else {
			ret = Math.round( dollars, 2) ;
		}

		return ret;
	}

	return false;
}

// PLAY SOUND
function playSound( soundfile_ogg, soundfile_mp, soundfile_ma ) {
	if ( "Audio" in window ) {
		var a = new Audio();
		if ( !!( a.canPlayType && a.canPlayType( 'audio/ogg; codecs="vorbis"' )
				.replace( /no/, '' ) ) )
			a.src = soundfile_ogg;
		else if ( !!( a.canPlayType && a.canPlayType( 'audio/mpeg;' ).replace( /no/,
				'' ) ) )
			a.src = soundfile_mp;
		else if ( !!( a.canPlayType && a.canPlayType(
				'audio/mp4; codecs="mp4a.40.2"' ).replace( /no/, '' ) ) )
			a.src = soundfile_ma;
		else
			a.src = soundfile_mp;

		a.autoplay = true;

	}
}

// VALIDATE SITE INPUT TO PREVENT INJECTION
function validateInputContent( input ) {
	if ( input ) {
		return input.replace( /</g, "&lt;" ).replace( />/g, "&gt;" );
	}

	return input;
}

// TRANSFORM STRING TO SLUG
function sanitizeTitle( str ) {
	if ( str ) return encodeURIComponent( str );

	return false;
}

// GENERATE RANDOM NUMBER
function generateNumber( restricted ) {
	restricted = restricted === undefined ? [] : restricted;

	var rand = Math.floor( Math.random() * 10 );

	if ( jQuery.inArray( rand, restricted ) === -1 ) {
		return rand;

	} else {
		return generateNumber();

	}
}

// ADD LOADER
function addLoader( class_name ) {
	jQuery( class_name ).prepend( '<div class="ui active inverted dimmer"><div class="ui loader"></div></div>' );
}

// LOAD CONTENT WITHOUT REFRESH
function refreshContent( class_name, callback ) {
	if ( wpj_vars.live_notify ) {

		jQuery( class_name ).load( ' ' + class_name + ' > *', function( response, status, xhr ) {
			// remove loader
			jQuery( '.ui.active.inverted.dimmer' ).remove();

			// init Semantic UI
			if ( typeof jQuery.fn.wpjSemanticInit == 'function' ) jQuery.fn.wpjSemanticInit();

			// load more
			if ( typeof wpj_display_load_more_button === 'function' ) wpj_display_load_more_button();

			// user profile page
			if ( class_name == '.profile-main-content.user-portfolio-wrapper' ) {
				jQuery.fn.wpjDropzoneUploaderInit();
				wpj_initialize_portfolio_carousel();
			}

			if ( class_name == '.info-widget.user-certification-wrapper' )
				wpj_hide_up_certification_not_expire();

			if ( class_name == '.user-skills-wrapper' || class_name == '.info-widget.user-education-wrapper' )
				jQuery.fn.wpjUploadifiveUploaderInit();

			// order page
			if ( class_name == '.order-timer-wrapper' ) {
				if ( jQuery( '#wpj-front-scripts-js-extra' )[0] && jQuery( response ).find( '#wpj-front-scripts-js-extra' )[0] ) {
					jQuery( '#wpj-front-scripts-js-extra' ).replaceWith( jQuery( response ).find( '#wpj-front-scripts-js-extra' )[0].outerHTML );
				}
				jQuery.fn.wpjFlipTimerInit();
			}

			if ( class_name == '#order-feedback-form-wrapper' ) {
				if ( jQuery( '.wpj-review-work-sample' ) ) {
					var is_rtl = typeof wpj_vars !== 'undefined' && wpj_vars.is_rtl ? true : false;
					wpj_initialize_wpj_carousel( is_rtl ); // work sample carousel
				}
			}

			// pm page
			if ( class_name == '.thread-list-wrapper' || class_name == '.pm-list' )
				wpj_init_attachments_gallery();

			// activate/deactivate/delete
			if ( class_name == '.kt-tabs-content-wrap' )
				wpj_reinit_kadence_tabs(); // for page builder

			// header
			if ( class_name == '.header-wrapper.header-pc' )
				wpj_init_search_autocomplete_elements();

			if ( typeof initLiveNotifications === 'function' ) initLiveNotifications();

			if (typeof callback === 'function') {
				callback();

			} else if (typeof window[callback] === 'function') {
				window[callback]();

			}

		});

	} else location.reload();
}

// REMOVE STRING
function removeCommaString( list, string ) {
	var elements     = list.split( "," );
	var remove_index = elements.indexOf( string );

	elements.splice( remove_index, 1 );

	return elements.join( "," );
}

// COPY
function copyString( selector ) {
	var $temp = jQuery( "<input>" );
	jQuery( "body" ).append( $temp );
	$temp.val( jQuery( selector ).text() ).select();
	document.execCommand( "copy" );
	$temp.remove();
}