Skip to content

Instantly share code, notes, and snippets.

@robertuniqid
Created May 10, 2021 21:27
Show Gist options
  • Save robertuniqid/77b87bd03e2227a01ad5200a24db1668 to your computer and use it in GitHub Desktop.
Save robertuniqid/77b87bd03e2227a01ad5200a24db1668 to your computer and use it in GitHub Desktop.
Editable Mentions Attempt - eLearnCommerce.
eLearnCommerce.Library.Editablementions = {
configuration : {
container_class : 'wpep-discussion-mention-item',
container_user_id_attr : 'data-wpep-mention-user-id',
image_class : 'wpep-discussion-mention-item-image',
name_class : 'wpep-discussion-mention-item-name'
},
_currentXHRSearch : false,
Init : function( targetElement ) {
let objectInstance = this,
libraryArgs = this._getLibraryArgsForTarget( targetElement );
targetElement.find( '.' + objectInstance.configuration.container_class + ' .' + objectInstance.configuration.name_class ).each( function() {
jQuery(this).attr( 'data-ec-original-value', jQuery(this).html() );
});
targetElement
.off( "change." + libraryArgs.namespace + " keydown." + libraryArgs.namespace + " input." + libraryArgs.namespace )
.on( "change." + libraryArgs.namespace + " keydown." + libraryArgs.namespace + " input." + libraryArgs.namespace, function( event ) {
let _current_word = objectInstance._getCurrentFocusWord( targetElement[0] );
if( _current_word.indexOf( "@" ) === 0 && _current_word.length > 3 ) {
eLearnCommerce.Library.Editablementions._handleSearch( _current_word, targetElement, libraryArgs );
return;
}
objectInstance._destroySearchResults();
jQuery(this).find( '.' + objectInstance.configuration.container_class ).each( function() {
let _mentionNameElement = jQuery(this).find( '.' + objectInstance.configuration.name_class ),
mention_content = _mentionNameElement.html();
if( _mentionNameElement.attr( 'data-ec-original-value' ) !== mention_content ) {
if( mention_content.indexOf( _mentionNameElement.attr( 'data-ec-original-value' ) ) === 0 ) {
_mentionNameElement.html( _mentionNameElement.attr( 'data-ec-original-value' ) );
} else {
let tokens = _mentionNameElement.attr( 'data-ec-original-value' ).split( ' ' );
tokens.pop();
_mentionNameElement.attr( 'data-ec-original-value', tokens.join( " " ) )
.html( tokens.join( " " ) );
}
mention_content = _mentionNameElement.html();
if( mention_content.replaceAll( '<br>', '' ) !== '' )
eLearnCommerce.Library.Editablementions._moveCaretFromMention( jQuery(this), targetElement );
}
if( mention_content.replaceAll( '<br>', '' ) === '' ) {
jQuery(this).remove();
return true;
}
});
});
},
_moveCaretFromMention : function( mentionObject, contentEditableObject ) {
let nodes = contentEditableObject[0].childNodes,
_target = false;
jQuery.each( nodes, function( _key, _node ) {
if( mentionObject[0].isEqualNode( _node ) ) {
_target = _key;
return false;
}
});
if( _target === false )
return;
if( typeof nodes[ _target + 1 ] !== "undefined" ) {
if( nodes[ _target + 1 ].nodeName === 'BR' ) {
if( typeof nodes[ _target + 2 ] === 'undefined' ) {
mentionObject.next().after( "<br>" );
_target = contentEditableObject[0].childNodes[ _target + 2 ];
} else {
_target = nodes[ _target + 2 ];
}
} else {
_target = nodes[ _target + 1 ];
}
} else {
mentionObject.after( "<span>&nbsp;</span>" );
_target = contentEditableObject[0].childNodes[ _target + 1 ];
}
if( false !== _target )
this.__moveCaretInNode( _target )
},
_getCurrentFocusWord : function( contentEditableNode ) {
let position = this._getCaretPosition( contentEditableNode ),
content = contentEditableNode.textContent;
if( content[position] === ' ' )
position--;
// Get the start and end index
let startPosition = content.lastIndexOf(' ', position);
startPosition = startPosition === content.length ? 0 : startPosition;
let endPosition = content.indexOf(' ', position);
endPosition = endPosition === -1 ? content.length : endPosition;
return content.substring(startPosition + 1, endPosition);
},
_getCaretPosition : function( contentEditableNode ) {
let caretOffset = 0;
if ( typeof window.getSelection !== "undefined" ) {
let range = window.getSelection().getRangeAt(0);
let preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents( contentEditableNode );
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
} else if ( typeof document.selection !== "undefined" && document.selection.type !== "Control" ) {
let textRange = document.selection.createRange();
let preCaretTextRange = document.body.createTextRange();
preCaretTextRange.moveToElementText( contentEditableNode );
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
},
_getCaretCoordinates : function() {
let x = 0,
y = 0;
const isSupported = typeof window.getSelection !== "undefined";
if ( !isSupported)
return false;
const selection = window.getSelection();
if (selection.rangeCount !== 0) {
const range = selection.getRangeAt(0).cloneRange();
range.collapse(true);
const rect = range.getClientRects()[0];
if (rect) {
x = rect.left;
y = rect.top;
}
}
return {
x : x,
y : y
};
},
__moveCaretInNode : function( targetNode ) {
let range = document.createRange(),
sel = window.getSelection();
range.setStart( targetNode, 1 );
range.collapse(false );
sel.removeAllRanges();
sel.addRange(range);
},
_getLibraryArgsForTarget : function( targetElement ) {
return JSON.parse( targetElement.attr( 'data-ec-library-args' ) );
},
_handleSearch : function( search_term, contentEditableObject, libraryArgs ) {
let resultContainer = jQuery( "#ec-editable-mentions-popup-results" ),
coords = this._getCaretCoordinates();
if( resultContainer.length === 0 ) {
jQuery( "body" ).append( '<div id="ec-editable-mentions-popup-results"></div>' );
resultContainer = jQuery( "#ec-editable-mentions-popup-results" );
} else if( resultContainer.attr( 'data-ec-search-term' ) === search_term )
return;
resultContainer.attr( 'data-ec-search-term', search_term )
.css( "left", coords.x )
.css( "top", coords.y );
resultContainer.html( ec_element_loader( 'mini' ) );
if( eLearnCommerce.Library.Editablementions._currentXHRSearch !== false )
eLearnCommerce.Library.Editablementions._currentXHRSearch.abort();
eLearnCommerce.Library.Editablementions._currentXHRSearch = eLearnCommerce.Data.fetch(
libraryArgs.request_path,
ec_parse_args( {
'search_term' : search_term.replace( "@", "" ),
}, libraryArgs.request_data ),
function( response ) {
eLearnCommerce.Library.Editablementions._currentXHRSearch = false;
if( jQuery.isEmptyObject( response.results ) ) {
eLearnCommerce.Library.Editablementions._destroySearchResults();
return;
}
let _content = '', i = 0;
jQuery.each( response.results, function( _result_key, result ) {
if( i >= 5 )
return false;
_content += '<div class="wpep-discussion-mention-item-selection">' +
'<span class="wpep-discussion-mention-item" data-wpep-mention-user-id="' + result.id + '">' +
'<img src="' + result.image + '" class="wpep-discussion-mention-item-image"/>' +
'<span class="wpep-discussion-mention-item-name" data-ec-original-value="' + result.name + '">' + result.name + '</span>' +
'</span>' +
'</div>';
i++;
});
resultContainer.html( _content );
resultContainer.find( '.wpep-discussion-mention-item-selection' ).off( "click" ).on( "click", function() {
let current_content = contentEditableObject.html(),
current_mention = jQuery(this).html() + '<span>&nbsp;</span>';
current_content = current_content.replace( search_term, current_mention );
contentEditableObject.html( current_content );
eLearnCommerce.Library.Editablementions._destroySearchResults();
eLearnCommerce.Library.Editablementions._moveCaretFromMention(
contentEditableObject.find( '[data-wpep-mention-user-id="' + jQuery(this).find( ' > .wpep-discussion-mention-item' ).attr('data-wpep-mention-user-id') + '"]' ),
contentEditableObject
);
});
}, resultContainer, true );
},
_destroySearchResults : function() {
jQuery( "#ec-editable-mentions-popup-results" ).remove();
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment