229 lines
7.7 KiB
JavaScript
Executable File
229 lines
7.7 KiB
JavaScript
Executable File
|
|
/* ===================================================
|
|
* jqueryaddDropCap.js v1.0.1
|
|
* ===================================================
|
|
* (c) 2015 Nicolas Guillaume, Nice, France
|
|
* addDropCap plugin may be freely distributed under the terms of the GNU GPL v2.0 or later license.
|
|
*
|
|
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* Target the first letter of the first element found in the wrapper
|
|
*
|
|
* =================================================== */
|
|
(function ( $ ) {
|
|
//defaults
|
|
var pluginName = 'addDropCap',
|
|
defaults = {
|
|
wrapper : ".entry-content",
|
|
minwords : 50,
|
|
skipSelectors : { //defines the selector to skip when parsing the wrapper also if they are children of an element
|
|
tags : ['IMG' , 'IFRAME', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE'],
|
|
classes : [],
|
|
ids : []
|
|
}
|
|
};
|
|
|
|
function Plugin( element, options ) {
|
|
this.element = element;
|
|
this.options = $.extend( {}, defaults, options) ;
|
|
this._defaults = defaults;
|
|
this._name = pluginName;
|
|
this.init();
|
|
}
|
|
|
|
//can access this.element and this.option
|
|
Plugin.prototype.init = function () {
|
|
var $_target = this._get_dropcap_el();
|
|
//if there's text and enough words, then apply a drop cap
|
|
if ( $_target && this.options.minwords <= this._countWords( $_target.text() ) )
|
|
this._may_be_add_dc( $_target );
|
|
};
|
|
|
|
|
|
//@return : $ element or false
|
|
//recursive function. parse this.wrapper to find the first eligible element with text
|
|
Plugin.prototype._get_dropcap_el = function( _requested_el ) {
|
|
var $_first_el = _requested_el || $( this.options.wrapper ).find( this.element ).first(),
|
|
_first_el_text = this._get_real_text( $_first_el.text() );
|
|
|
|
if ( ! this._is_authorized( $_first_el ) && $_first_el.next().length )
|
|
return this._get_dropcap_el( $_first_el.next() );
|
|
else if ( this._is_authorized( $_first_el ) && _first_el_text )
|
|
return $_first_el;
|
|
else if ( $_first_el.next().length )
|
|
return this._get_dropcap_el( $_first_el.next() );
|
|
//get me out of here
|
|
return;
|
|
};
|
|
|
|
//@return : string
|
|
//clean spaces and special characters
|
|
Plugin.prototype._get_real_text = function( _text ) {
|
|
_text.replace(/ /g, '').replace(/ /g, '');
|
|
return this._removeSpecChars( _text );
|
|
};
|
|
|
|
//@return :boolean
|
|
//check if the selector is in the 'to skip' list
|
|
Plugin.prototype._is_authorized = function( $_el ) {
|
|
//check if underscore is loaded first
|
|
if ( 'function' != typeof(_) )
|
|
return true;
|
|
if ( ! $_el[0] || ! $_el[0].tagName )
|
|
return;
|
|
if ( ! this._is_tag_allowed( $_el ) )
|
|
return;
|
|
if ( ! this._are_children_tag_allowed( $_el ) )
|
|
return;
|
|
if ( ! this._is_selector_allowed( $_el, ['ids' , 'classes'] ) )
|
|
return;
|
|
|
|
return true;
|
|
};
|
|
|
|
|
|
//@return : void
|
|
//at this stage, the target has text, no need to check it
|
|
Plugin.prototype._may_be_add_dc = function( $_target ) {
|
|
var // _first_el_text = $_target.text(),
|
|
_first_word = '',
|
|
_split_text = $_target.text().replace(/ /g , ' ').split(' ');
|
|
if ( ! _.isArray(_split_text) )
|
|
return;
|
|
|
|
//get the first word => it can't be a space due to previous treatment
|
|
if ( _split_text.length )
|
|
_first_word = _split_text[0];
|
|
|
|
//cClean it
|
|
_first_word = this._removeSpecChars( _first_word );
|
|
|
|
if ( ! _first_word.charAt(0) )
|
|
return;
|
|
|
|
var _first_letter = _first_word.charAt(0),
|
|
_rest_of_word = _first_word.substr(1),
|
|
_drop_capped = '',
|
|
_html = '';
|
|
|
|
_first_letter = ['<span class="tc-dropcap">' , _first_letter, '</span>'].join('');
|
|
_drop_capped = [ _first_letter , _rest_of_word ].join( '' );
|
|
|
|
//replace the first occurence only
|
|
_html = $_target.html().replace( _first_word , _drop_capped );
|
|
|
|
//write
|
|
$_target.html(_html);
|
|
};
|
|
|
|
|
|
/********
|
|
* HELPERS
|
|
*********/
|
|
/*
|
|
* @params string : ids or classes
|
|
* @return boolean
|
|
*/
|
|
Plugin.prototype._is_selector_allowed = function( $_el , sel_types ) {
|
|
//check if option is well formed
|
|
if ( 'object' != typeof( this.options.skipSelectors ) )
|
|
return true;
|
|
var self = this,
|
|
_filtered = sel_types.filter( function( sel_typ ) { return false === self._is_sel_type_allowed( $_el, sel_typ ); } );
|
|
return 0 === _filtered.length;
|
|
};
|
|
|
|
|
|
/*
|
|
* @return boolean
|
|
*/
|
|
Plugin.prototype._is_sel_type_allowed = function( $_el, sel_typ ) {
|
|
//check if option is well formed
|
|
if ( !this.options.skipSelectors[sel_typ] || !Array.isArray( this.options.skipSelectors[sel_typ] ) )
|
|
return true;
|
|
|
|
var _attr = 'ids' == sel_typ ? 'id' : 'class';
|
|
|
|
//check if option is well formed
|
|
if ( 'object' != typeof(this.options.skipSelectors) || ! this.options.skipSelectors[sel_typ] || !Array.isArray( this.options.skipSelectors[sel_typ] ) )
|
|
return true;
|
|
|
|
var _elSels = ! $_el.attr( _attr ) ? [] : $_el.attr( _attr ).split(' '),
|
|
_selsToSkip = this.options.skipSelectors[sel_typ],
|
|
_current_filtered = _elSels.filter( function( name ) { return -1 != $.inArray( name , _selsToSkip ) ;});
|
|
|
|
var _pref = 'ids' == sel_typ ? '#' : '.',
|
|
_children_filtered = _selsToSkip.filter( function( name ) {
|
|
return 0 !== $_el.find(_pref + name).length;
|
|
} );
|
|
|
|
return 0 === $.merge( _current_filtered , _children_filtered ).length;
|
|
};
|
|
|
|
|
|
/*
|
|
* @return boolean
|
|
*/
|
|
Plugin.prototype._is_tag_allowed = function( $_el ) {
|
|
//check if option is well formed
|
|
if ( 'object' != typeof(this.options.skipSelectors) || ! _.isArray( this.options.skipSelectors.tags ) )
|
|
return true;
|
|
//Try to find current element tag name among the forbidden list
|
|
return -1 == _.indexOf( _.map( this.options.skipSelectors.tags , function(_tag) { return _tag.toUpperCase(); } ), $_el[0].tagName );
|
|
};
|
|
|
|
|
|
/*
|
|
* @return boolean
|
|
*/
|
|
Plugin.prototype._are_children_tag_allowed = function( $_el ) {
|
|
//check if option is well formed
|
|
if ( 'object' != typeof(this.options.skipSelectors) || ! _.isArray( this.options.skipSelectors.tags ) )
|
|
return true;
|
|
//has children ?
|
|
if ( 0 === $_el.children().length )
|
|
return true;
|
|
|
|
var //childTagName = $_el.children().first()[0].tagName,
|
|
_tagToSkip = this.options.skipSelectors.tags,
|
|
_filtered = _tagToSkip.filter( function(_tag) { return 0 !== $_el.find(_tag).length;} );
|
|
|
|
return 0 === _filtered.length;
|
|
};
|
|
|
|
|
|
//@return : number
|
|
Plugin.prototype._countWords = function( _expr ) {
|
|
if ( 'string' != typeof( _expr ) )
|
|
return 0;
|
|
_expr = _expr.replace(' ' , ' ');
|
|
return (_expr.split(' ')).length;
|
|
};
|
|
|
|
//Remove all characters from string but alphanumeric and -
|
|
//@return : string
|
|
Plugin.prototype._removeSpecChars = function( _expr , _replaceBy ) {
|
|
_replaceBy = _replaceBy || '';
|
|
return 'string' == typeof(_expr) ? _expr.replace(/[^\w-?!\u00bf-\u00ff]/g, _replaceBy ) : '';
|
|
};
|
|
|
|
//@return : string or false
|
|
Plugin.prototype._stripHtmlTags = function( expr ) {
|
|
return ( expr && 'string' == typeof(expr) ) ? expr.replace(/(<([^>]+)>)/ig,"") : false;
|
|
};
|
|
|
|
|
|
/**********
|
|
* CONSTRUCT
|
|
**********/
|
|
// 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);
|