Skip to content

Instantly share code, notes, and snippets.

@clohr
Last active August 7, 2017 19:35
Show Gist options
  • Save clohr/f09220ba8fb014368fae348ff9e821f7 to your computer and use it in GitHub Desktop.
Save clohr/f09220ba8fb014368fae348ff9e821f7 to your computer and use it in GitHub Desktop.
@ mention pattern matching
const mentions = [
'Al Dufresne',
'Vella Trent',  
'Yolande Casimir',
'Shavonda Hilgendorf',  
'Jamaal Sumner',  
'Alex Tetterton',  
'Adria Shedd',  
'Lindsay Legree',  
'Karey Hedgepeth',  
'Rey Vannest',  
'Tula Nemitz',  
'Quiana Presgraves',  
'Merle Carbaugh',  
'Matt Mckillip',  
'Heike Leak',  
'Leslie Rauch',  
'Winifred Rochester',  
'Maurine Capra',  
'Marty Sabo',  
'Dinorah Colon',  
'Meta Jobe',  
'Jc Stott',  
'Lauran Grange',  
'Kattie Peil',  
'Sandie Eure',  
'Stella Steed',  
'Rubie Thorson',  
'Cindi Nemeth',  
'Sau Hollister',  
'Javier Farquhar',  
'Laura Uriarte',  
'Terrance Toal',  
'Reagan Masten',  
'Candra Peterka',  
'Tran Dawn',  
'Catherin Brase',  
'Christina Toner',  
'Lloyd Fury',  
'Kathlyn Trueman',  
'Treena Blowers',  
'Gilbert Yochum',  
'Kimber Baden',  
'Spring Fermin',  
'Errol Hovey',  
'Iraida Rawles',  
'Lance Ertl',  
'Aida Hawes',  
'Latasha Jeffries',  
'Na Bibbins',
'Flor Devane' 
]
const comments = document.getElementById('comments')
const mentionsContainer = document.getElementById('mentionsContainer')
const atIndex = (str) => str.indexOf('@')
const getAtMention = (str) => {
const at = atIndex(str)
return str.substring(at + 1)
}
const getMatches = (userInput) => (txtToMatch) => {
const exp = getAtMention(userInput)
const regex = new RegExp(exp, 'gi')
const matches = txtToMatch.match(regex)
return matches && matches.length > 0
}
var replaceAt = (str) => {
const userInput = comments.value
const start = atIndex(userInput)
const end = comments.selectionEnd
const newInput = userInput.substr(0, start) + ' ' + str + ' ' + userInput.substr(end)
comments.value = newInput
mentionsContainer.style.visibility = 'hidden'
}
comments.addEventListener('keyup', evt => {
// get user input
const userInput = evt.target.value
if (userInput.indexOf('@') === -1) {
return mentionsContainer.style.visibility = 'hidden'
}
// display @ mentions
mentionsContainer.style.visibility = 'visible'
// check against list
const matchFilter = getMatches(userInput)
const matches = mentions.filter(matchFilter)
// updates mentions
const matchedResults = matches.length > 0 ? matches : mentions
const content = matchedResults.map(c => `<li onclick="replaceAt('${c}')">${c}</li>`).join('')
mentionsContainer.innerHTML = content
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<link rel="stylesheet" href="styles.css"/>
</head>
<body>
<input id="comments" />
<ul id="mentionsContainer" class="mentions"></ul>
</body>
</html>
input {
background: white;
border: solid 1px #666;
outline: none;
padding: 4px;
}
input:focus {
border: solid 1px blue;
}
.mentions {
background: white;
border: solid 1px #ddd;
margin: 0;
padding: 0;
width: 300px;
height: 400px;
overflow-y: auto;
visibility: hidden;
}
.mentions li {
border-top: solid 1px #ddd;
display: block;
margin: 0;
padding: 0 10px;
width: 100%;
line-height: 40px;
height: 40px;
overflow: hidden;
cursor: pointer;
}
.mentions:firstChild {
border-top: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment