Using ! or # in Summernote hint content - javascript

In my summernote hint option I have the following
hint: {
match: /\B[#!](\w*)$/,
search: function (keyword, callback) {
callback($.grep(mentions, function (i) {
user = mentionData[i];
return user.name.indexOf(keyword) === 0;
}));
},
template: function...
content: function (i) {
var user = mentionData[i];
return $('<span>#' + user.username + '</span>')[0];
}
}
I want to be able to insert the # or ! symbol (whichever one the user initiated the hint with) into the content option. Is there a way to pass the keyword to the content function? or is there a way specific to summernote to do this?

You can use array hints, example:
hint:[
{
words: ['apple', 'orange', 'watermelon', 'lemon'],
match: /\b(\w{1,})$/,
search: function (keyword, callback) {
callback($.grep(this.words, function (item) {
return item.indexOf(keyword) === 0;
}));
},
{
mentions: ['jayden', 'sam', 'alvin', 'david'],
match: /\B#(\w*)$/,
search: function (keyword, callback) {
callback($.grep(this.mentions, function (item) {
return item.indexOf(keyword) == 0;
}));
},
content: function (item) {
return '#' + item;
}
}
]
}
},

Related

Can I disable completion filtering in Ace Editor?

This plunker uses a rhyming dictionary to do autocompletion.
var langTools = ace.require("ace/ext/language_tools");
var editor = ace.edit("editor");
editor.setOptions({enableBasicAutocompletion: true});
// uses http://rhymebrain.com/api.html
var rhymeCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
if (prefix.length === 0) { callback(null, []); return }
$.getJSON(
"http://rhymebrain.com/talk?function=getRhymes&word=" + prefix,
function(wordList) {
// wordList like [{"word":"flow","freq":24,"score":300,"flags":"bc","syllables":"1"}]
callback(null, wordList.map(function(ea) {
return {name: ea.word, value: ea.word, score: ea.score, meta: "rhyme"}
}));
})
}
}
langTools.addCompleter(rhymeCompleter);
For example, type "trace" and hit ctrl-space, and only a few suggestions pop up (retrace, interlace, interface).
The rhyming dictionary actually suggested many other matches, and they were passed in to the callback, but internally Ace filtered them out because they don't contain the letters "t", "r", "a", "c", and "e". Is there a way to bypass that filter so that it suggests all of the things that were passed to the callback?
The Autocompletion is filtered by ace in the autocompleter file. But you can set insertMatch to avoid this filter,
insertMatch: function(editor, data) {
editor.completer.insertMatch({value: data.value})
});
You can update the callback function in this way:
callback(null,
wordList.map(function (word) {
return {
caption: word,
value: word,
completer: {
insertMatch: function (editor, data) {
editor.completer.insertMatch({value: data.value})
}
}
}

Lodash/JS - Convert _.find statement to _.forEach

I'm having trouble converting the following Lodash statement to something that works in an application that I inherited at work and am trying to fix bugs in. At the moment, we are having issues with only one device on our system returning when two devices have the same name and the following code seems to be the culprit as it would only return the first "true" value in an array:
var group = _.find(groupList, {id: id});
How would I successfully convert this to a statement that iterates over all objects in an array and then returns those objects? I've tried the following options to no avail:
var group = _.filter(groupList, {id: id});
and
var group = _.every(groupList, {id: id});
and
var group = _.forEach(groupList, {id: id})
return {id};
I know I am probably missing something in my syntax. Any help would be much appreciated. Running Lodash v3.7.0
Here's the rest of the code in the directive in case anyone is interested or sees something else I might be missing:
define(['./../_module'], function (directives) {
'use strict';
directives.directive('dmGroupedList', ['$compile', '$state', 'APP_CONSTANTS', function ($compile, $state, APP_CONSTANTS) {
return {
restrict: 'A',
scope: {
items: '=',
groupBy: '=',
actions: '=',
nonameGroupLabel: '='
},
templateUrl: function (elem, attrs) {
return attrs.templateUrl || 'views/shared-templates/grouped-list.html';
},
link: function (scope, element, attrs) {
scope.$watchGroup(['items', 'groupBy', 'nonameGroupLabel'], function () {
scope.groupList = [];
scope.groupedItems = {};
var actions = scope.actions[scope.groupBy];
_.forEach(scope.items, function (item) {
scope.handlers.getGroups(scope.groupList, item, scope.items, scope.groupBy, actions);
});
_.forEach(scope.groupList, function (group) {
var items = scope.groupedItems[group.id];
items = _.sortBy(items, function (item) {
return item.description;
});
scope.groupedItems[group.id] = items;
});
var groupsToSort = _.where(scope.groupList, {unassigned: false});
var unassignedGroups = _.sortBy(_.where(scope.groupList, {unassigned: true}), 'name');
scope.groupList = _.sortBy(groupsToSort, function (group) {
return group.name;
});
//adds unassigned groups to a new array via the javascript "push" method
if (angular.isDefined(unassignedGroups)) {
for (var i = 0; i < unassignedGroups.length; i++) {
scope.groupList.push(unassignedGroups[i]);
}
}
});
scope.handlers = {
getGroups: function (groupList, item, items, groupBy, actions) {
var group = item[groupBy];
if (_.isEmpty(group)) {
scope.handlers.addGroupToList(groupList, APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE, items, groupBy, item, actions, scope);
}
else {
if (angular.isArray(group) || angular.isObject(group)) {
_.forEach(group, function (groupName) {
if (groupName == APP_CONSTANTS.ZERO) {
scope.handlers.addGroupToList(groupList, APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE, items, groupBy, item, actions, scope);
return;
}
scope.handlers.addGroupToList(groupList, groupName, items, groupBy, item, actions, scope);
})
} else {
scope.handlers.addGroupToList(groupList, group, items, groupBy, item, actions, scope);
}
}
},
addGroupToList: function (groupList, groupId, items, groupBy, item, handlers, scope) {
var id = _.camelCase(groupId);
var group = _.find(groupList, {id: id});
//var group = _.forEach(groupList, {id: id})
//return {id};
if (!group) {
var name = '';
var unassigned = false;
var link = null;
if (groupId == APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE || groupId == APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE_PARENT_ID) {
if (groupId == APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE_PARENT_ID) {
name = APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE;
} else {
name = APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.UNASSIGNED;
}
unassigned = true;
} else {
link = handlers.getGroupLink(groupId);
name = handlers.getGroupName(groupId, items);
}
group = {id: id, name: name, unassigned: unassigned, link: link};
groupList.push(group);
}
scope.groupedItems[group.id] = scope.groupedItems[group.id] || [];
if (angular.isDefined(handlers.processingGroup)) {
handlers.processingGroup(group, groupList, groupId, items, groupBy, item, handlers, scope);
} else {
scope.groupedItems[group.id].push({
description: handlers.getItemDescription(item),
link: handlers.getItemLink(item)
})
}
}
};
}
};
}]);
});
You can just use filter:
var group = groupList.filter((group) => group.id === id);
EDIT: to return only the element, and not an array, when there is only one match, you can do the following:
var checkSingle = (groups) => groups.length === 1 ? groups[0] : groups;
var group = checkSingle(groupList.filter((group) => group.id === id));
You can _(groupList).groupBy('id').get(id):
var groupList = [
{ id: 1, name: 'site' },
{ id: 2, name: 'test' },
{ id: 2, name: 'prod' },
{ id: 3, name: 'dev' },
{ id: 4, name: 'back' },
{ id: 4, name: 'front' },
{ id: 5, name: 'sprint' }
];
console.log(_(groupList).groupBy('id').get(2));
console.log(_(groupList).groupBy('id').get(3));
console.log(_(groupList).groupBy('id').get(4));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Customizing easyAutoComplete

var options = {
url: function (phrase) {
return "location/autoComplete?key=" + phrase;
},
getValue: "cityName",
template: {
type: "custom",
method: function (value, item) {
return value + ", " + item.stateName;
}
},
list: {
onClickEvent: function () {
var selectedLongitude = $("#autoCompleteSearch").getSelectedItemData().longitude;
var selectedLatitude = $("#autoCompleteSearch").getSelectedItemData().latitude;
userPos = {
lat: Number(selectedLatitude),
lng: Number(selectedLongitude)
};
map.setCenter(userPos);
map.setZoom(17)
},
showAnimation: {
type: "fade", //normal|slide|fade
time: 400,
callback: function () {
}
},
hideAnimation: {
type: "slide", //normal|slide|fade
time: 400,
callback: function () {
}
}
}
};
This is the code I am using right now to fetch a remote webservice data. Now I need to get the data and remove the duplicate "city names". Also I need to show "Data not available" or some custom method when there is no data from the webservice. I am kind of stuck. Would be great if someone could point me on how to achieve this.
You can get rid of duplicates using a helper function:
function removeDuplicates(input) {
if (!input) { //Falsy input
return input;
}
var isArray = Array.isArray(input) ? [] : {};
var items = [];
var output = {};
for (var key in input) {
if (items.indexOf(input[key]) < 0) {
items.push(input[key]);
if (!isArray) {
output[key] = input[key];
}
}
}
return isArray ? items : output;
}
You can show your custom text if Array.isArray(input) ? (input.length === 0) : (Object.keys(input).length === 0 && input.constructor === Object).

Semantic UI - Search API: how I can highlight certain characters that match the query?

I have a problem when I want to highlight certain characters that match the query in search module.
an example is like this forum: https://forums.meteor.com
Previously, I already asked this issue at https://github.com/Semantic-Org/Semantic-UI/issues/4930#issuecomment-275011130, but until now not been resolved.
here is my current demo: https://jsfiddle.net/agaust/5854gae9/4/
$(document).ready(function() {
$.fn.api.settings.api = {
'search': 'https://gist.githubusercontent.com/agusmakmun/e258a3243367105c32919c083eb577fe/raw/8b0038b0141f5813c03baece0b2730e17216f8c9/result-data.json?q={query}'
};
$('.ui.search.quick-search').search({
type : 'category',
minCharacters : 1, // just under devel to make it easy
apiSettings : {
action: 'search',
onResponse: function(searchApiResponse) {
var response = {
results : {},
//action : searchApiResponse.action // dict action
};
// translate `searchApiResponse` response to work with search
var numbThreads = 0, numbUsers = 0;
$.each(searchApiResponse.items, function(index, item) {
var
model = item.model || 'Unknown',
maxResults = 6,
maxItems = maxResults/2 // max results per-Category
;
if(index >= maxResults) {
return false;
}
// create new model category
if(response.results[model] === undefined) {
response.results[model] = {
name : model,
results : []
};
}
if(item.model === 'Threads') {
if ((numbThreads < maxItems) || (numbUsers < numbThreads)) {
response.results[model].results.push({
title: item.title,
description: item.description,
url: item.url
});
}
numbThreads++;
}else if (item.model === 'Users') {
if ((numbUsers < maxItems) || (numbThreads < numbUsers)) {
response.results[model].results.push({
title: item.username,
description: item.username,
url: item.profile_url,
image: item.gravatar_url,
price: item.total_threads
});
}
numbUsers++;
}
});
// only showing the bottom action button if under limited
if (searchApiResponse.limited_items) {
response["action"] = searchApiResponse.action;
}
console.log(response);
return response;
}
}
});
});
any help would be apreciated.. :)

Dynamically autocomplete in ace editor

I want to update autocomplete suggestions according to the string.
aceeditorObj.completers.push({
getCompletions: function(editor, session, pos, prefix, callback) {
obj = editor.getSession().getTokenAt(pos.row, pos.column-count);
if(obj.value === "student"){
var wordList = ["name", "age" , "surname"];
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word,
meta: "static"
};
}));
}
}
});
Name, age and surname is added to the auto suggestion list. But the old ones are still there. How can I show only the new world list in the list of auto completion?
Try setting the language tools to blank after you call your completers function:
var langTools = ace.require("ace/ext/language_tools");
aceeditorObj.completers.push({
getCompletions: function(editor, session, pos, prefix, callback) {
obj = editor.getSession().getTokenAt(pos.row, pos.column-count);
if(obj.value === "student"){
var wordList = ["name", "age" , "surname"];
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word,
meta: "static"
};
}));
}
}
});
langTools.setCompleters([]); // This function should clear them

Categories

Resources