cl01/wp-content/themes/hueman/assets/front/js/libs/jquery-plugins/jqueryextLinks.js
2025-02-24 12:39:24 +08:00

177 lines
5.9 KiB
JavaScript
Executable File

//Target the first letter of the first element found in the wrapper
(function ( $ ) {
//defaults
var pluginName = 'extLinks',
defaults = {
addIcon : true,
iconClassName : 'tc-external',
newTab: true,
skipSelectors : { //defines the selector to skip when parsing the wrapper
classes : [],
ids : []
},
skipChildTags : ['IMG']//skip those tags if they are direct children of the current link element
};
function Plugin( element, options ) {
this.$_el = $(element);
this.options = $.extend( {}, defaults, options) ;
this._href = ( 'string' == typeof( this.$_el.attr( 'href' ) ) ) ? this.$_el.attr( 'href' ).trim() : '';
this.init();
}
Plugin.prototype.init = function() {
var self = this,
$_external_icon = this.$_el.next( '.' + self.options.iconClassName );
//if not eligible, then remove any remaining icon element and return
//important => the element to remove is right after the current link element ( => use of '+' CSS operator )
if ( ! this._is_eligible() ) {
if ( $_external_icon.length )
$_external_icon.remove();
return;
}
//add the icon link, if not already there
if ( this.options.addIcon && 0 === $_external_icon.length ) {
this.$_el.append('<span class="' + self.options.iconClassName + '">');
}
//add the target _blank, if not already there
if ( this.options.newTab && '_blank' != this.$_el.attr('target') )
this.$_el.attr('target' , '_blank');
};
/*
* @return boolean
*/
Plugin.prototype._is_eligible = function() {
var self = this;
if ( ! this._is_external( this._href ) )
return;
//is first child tag allowed ?
if ( ! this._is_first_child_tag_allowed () )
return;
//are ids and classes selectors allowed ?
//all type of selectors (in the array) must pass the filter test
if ( 2 != ( ['ids', 'classes'].filter( function( sel_type) { return self._is_selector_allowed(sel_type); } ) ).length )
return;
var _is_eligible = true;
// disallow elements whose parent has text-decoration: underline
// we want to exit as soon as we find a parent with the underlined text-decoration
$.each( this.$_el.parents(), function() {
if ( 'underline' == $(this).css('textDecoration') ){
_is_eligible = false;
return false;
}
});
return true && _is_eligible;
};
/********
* HELPERS
*********/
/*
* @params string : ids or classes
* @return boolean
*/
Plugin.prototype._is_selector_allowed = function( requested_sel_type ) {
if ( czrapp && czrapp.userXP && czrapp.userXP.isSelectorAllowed )
return czrapp.userXP.isSelectorAllowed( this.$_el, this.options.skipSelectors, requested_sel_type);
var sel_type = 'ids' == requested_sel_type ? 'id' : 'class',
_selsToSkip = this.options.skipSelectors[requested_sel_type];
//check if option is well formed
if ( 'object' != typeof(this.options.skipSelectors) || ! this.options.skipSelectors[requested_sel_type] || ! Array.isArray( this.options.skipSelectors[requested_sel_type] ) || 0 === this.options.skipSelectors[requested_sel_type].length )
return true;
//has a forbidden parent?
if ( this.$_el.parents( _selsToSkip.map( function( _sel ){ return 'id' == sel_type ? '#' + _sel : '.' + _sel; } ).join(',') ).length > 0 )
return false;
//has requested sel ?
if ( ! this.$_el.attr( sel_type ) )
return true;
var _elSels = this.$_el.attr( sel_type ).split(' '),
_filtered = _elSels.filter( function(classe) { return -1 != $.inArray( classe , _selsToSkip ) ;});
//check if the filtered selectors array with the non authorized selectors is empty or not
//if empty => all selectors are allowed
//if not, at least one is not allowed
return 0 === _filtered.length;
};
/*
* @return boolean
*/
Plugin.prototype._is_first_child_tag_allowed = function() {
//has children ?
if ( 0 === this.$_el.children().length )
return true;
var tagName = this.$_el.children().first()[0].tagName,
_tagToSkip = this.options.skipChildTags;
//check if tag to skip option is an array
if ( ! Array.isArray( _tagToSkip ) )
return true;
//make sure tags in option are all in uppercase
_tagToSkip = _tagToSkip.map( function( _tag ) { return _tag.toUpperCase(); });
return -1 == $.inArray( tagName , _tagToSkip );
};
/*
* @return boolean
*/
Plugin.prototype._is_external = function( _href ) {
//gets main domain and extension, no matter if it is a n level sub domain
//works also with localhost or numeric urls
var _main_domain = (location.host).split('.').slice(-2).join('.'),
_reg = new RegExp( _main_domain );
if ( 'string' != typeof( _href ) )
return;
_href = _href.trim();
if ( _href !== '' && _href != '#' && this._isValidURL( _href ) )
return ! _reg.test( _href );
return;
};
/*
* @return boolean
*/
Plugin.prototype._isValidURL = function( _url ){
var _pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
return _pattern.test( _url );
};
// prevents against multiple instantiations
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName,
new Plugin( this, options ));
}
});
};
})( jQuery );