window.addEventListener "trix-initialize", (e) => | |
Utility.TrixMentions.prepare($(e.target)) |
# Filter for use with https://github.com/jch/html-pipeline | |
# to extract mentioned user_ids | |
module HTML | |
class Pipeline | |
class TrixMentionFilter < Filter | |
attr_reader :mentioned_user_ids | |
def initialize(doc, context = nil, result = nil) | |
super doc, context, result | |
@mentioned_user_ids = [] | |
end | |
def call | |
process_attachments! do |attachment| | |
@mentioned_user_ids << attachment["user-id"].to_i | |
end | |
doc | |
end | |
def process_attachments! | |
doc.css("[data-trix-attachment]").each do |attachment_node| | |
attachment = JSON.parse(attachment_node.attribute('data-trix-attachment')) | |
next unless attachment["attachment-type"] == "trix-mention" | |
yield attachment | |
end | |
end | |
end | |
end | |
end |
window.Utility ||= {} | |
class Utility.TrixMentions | |
MENTIONS_PATH = "mentions-path" | |
MENTIONS_DIV_ID = "#trix-mentions-" | |
MENTIONS_INPUT_ID = MENTIONS_DIV_ID + "input-" | |
@prepare: ($trix) -> | |
mentionsDivForTrix = ($trix) -> | |
$(MENTIONS_DIV_ID + $trix.attr('trix-id')) | |
mentionsInputForTrix = ($trix) -> | |
$(MENTIONS_INPUT_ID + $trix.attr('trix-id')) | |
mentionsSelectizeForTrix = ($trix) -> | |
mentionsInputForTrix($trix).next('.selectize-control') | |
mentionsSelectizeDropdownForTrix = ($trix) -> | |
mentionsInputForTrix($trix).next('.selectize-dropdown') | |
createMentionsDivForTrix = ($trix) -> | |
$trix.after("<trix-mentions id='trix-mentions-"+ $trix.attr('trix-id') + "'><input id='trix-mentions-input-" + $trix.attr('trix-id') + "'></input></trix-mentions>") | |
initializeMentionsSelectize = ($trix) -> | |
$.getJSON $trix.data(MENTIONS_PATH), (result) -> | |
mentionsInputForTrix($trix).selectize | |
create: false | |
valueField: 'id' | |
labelField: 'name' | |
searchField: 'name' | |
sortField: 'name' | |
options: result.data | |
selectOnTab: true | |
onInitialize: -> | |
@.disable() | |
mentionsSelectizeForTrix($trix).css('left', -1000) | |
onItemAdd: (value, $item) -> | |
embed = "<span class='trix-mention'>@" + $item.text() + "</span>" | |
attachment = new Trix.Attachment | |
content: embed | |
'attachment-type': 'trix-mention' | |
'user-id': $item.data('value') | |
$trix[0].editor.setSelectedRange([$trix.data('last-position') - 1, $trix.data('last-position')]) | |
$trix[0].editor.deleteInDirection('forward') | |
$trix[0].editor.insertAttachment attachment | |
mentionsDivForTrix($trix).hide() | |
onBlur: -> | |
mentionsDivForTrix($trix).hide() | |
@.disable() | |
mentionsSelectizeForTrix($trix).css('left', -1000) | |
$trix.focus() | |
if @.items.length == 0 | |
$trix[0].editor.setSelectedRange([$trix.data('last-position') - 1, $trix.data('last-position')]) | |
$trix[0].editor.deleteInDirection('forward') | |
onDropdownClose: -> | |
mentionsDivForTrix($trix).hide() | |
onDropdownOpen: ($dropdown) -> | |
rect = $trix[0].editor.getClientRectAtPosition($trix[0].editor.getPosition()) | |
if rect != undefined | |
$dropdown.css('top', 34) | |
if rect.left + 200 > $trix.offset().left + $trix.width() | |
$dropdown.css('left', $trix.offset().left + $trix.width() - (rect.left + 210)) | |
onType: (str) -> | |
rect = $trix[0].editor.getClientRectAtPosition($trix[0].editor.getPosition()) | |
if rect.left + 200 > $trix.offset().left + $trix.width() | |
mentionsSelectizeDropdownForTrix($trix).css('left', $trix.offset().left + $trix.width() - (rect.left + 210)) | |
openMentionsSelectize = ($trix, editor) -> | |
$trix.data 'last-position', editor.getPosition() | |
mentionsInput = mentionsInputForTrix($trix) | |
mentionsSelectize = mentionsSelectizeForTrix($trix) | |
rect = editor.getClientRectAtPosition(editor.getPosition()) | |
mentionsSelectize.css('left', rect.left - 10) | |
mentionsSelectize.css('top', rect.top - 4) | |
mentionsInput[0].selectize.clear() | |
mentionsInput[0].selectize.enable() | |
mentionsDivForTrix($trix).show() | |
mentionsInput[0].selectize.focus() | |
if $trix.data(MENTIONS_PATH).length > 0 | |
createMentionsDivForTrix($trix) | |
initializeMentionsSelectize($trix) | |
$trix.on 'trix-change', -> | |
editor = @.editor | |
char = editor.getDocument().toString().charAt(editor.getPosition() - 1) | |
openMentionsSelectize($(@), editor) if char == '@' |
[data-trix-attachment] { | |
display: inline-block; | |
} | |
span.trix-mention + figcaption { | |
display: none; | |
} | |
trix-mentions { | |
.selectize-control { | |
position: fixed | |
} | |
.selectize-input { | |
border: none !important; | |
background: none !important; | |
box-shadow: none !important; | |
} | |
.selectize-control, .selectize-dropdown { | |
width: 200px !important; | |
z-index: 9999; | |
} | |
} |
@mitar, the autocomplete trigger is extremely primitive -- any time you hit "@", it's going to open the selectize control:
$trix.on 'trix-change', ->
editor = @.editor
char = editor.getDocument().toString().charAt(editor.getPosition() - 1)
openMentionsSelectize($(@), editor) if char == '@'
I expect you can expand the if char == '@'
conditional to do a better evaluation of context and decide if you want to call openMentionsSelectize.
I've spent the last couple hours trying to debug an error I'm getting and my JS skills just aren't there, especially with coffee thrown into the mix. Hopefully this will be an easy error on my part that you can direct me on how to resolve.
Line 82 of trix_mentions.js.coffee is what's triggering the error.
if $trix.data(MENTIONS_PATH).length > 0
Error as seen in Firefox:
TypeError: $trix.data(...) is undefined
Error as seen in Chrome:
Uncaught TypeError: Cannot read property 'length' of undefined
at Function.Utility.TrixMentions.TrixMentions.prepare (trix_mentions.self-857d9c9….js?body=1:105)
at mentionable_trix.self-9ca102d….js?body=1:4
at triggerEvent (trix.self-34b57b1….js?body=1:16)
at HTMLElement.notify (trix.self-34b57b1….js?body=1:21)
at trix.self-34b57b1….js?body=1:21
Utility.TrixMentions.TrixMentions.prepare @ trix_mentions.self-857d9c9….js?body=1:105
(anonymous) @ mentionable_trix.self-9ca102d….js?body=1:4
triggerEvent @ trix.self-34b57b1….js?body=1:16
notify @ trix.self-34b57b1….js?body=1:21
(anonymous) @ trix.self-34b57b1….js?body=1:21
I wasn't sure how I was supposed to set this up. I think all I need to configure is the path to my mentions, which I've done. Here is my config block:
MENTIONS_PATH = "/user/mentions?r"
MENTIONS_DIV_ID = "#trix-mentions-"
MENTIONS_INPUT_ID = MENTIONS_DIV_ID + "input-"
@lawso017, Any thoughts on how I should proceed? I'm running selectize.js 0.12.4 which appears to be the latest. Rails 5.1.2 on Ruby 2.4.1. Thanks!
@blimey85, the MENTIONS_PATH constant shouldn't need to be changed in your implementation. It's just defined as a constant to prevent typos in the code... we use the defined value "mentions-path" to identify the data attribute containing the path in the control.
In your case, you just need to ensure that your trix element has the data attribute:
data-mentions-path="/user/mentions?r"
defined.
This triggers autocomplete also inside the code element. Is there a way to prevent that?