Extract specific variables from a mixed string/JSON data - javascript

I am using Tagify with a custom AngularJS directive that I built, Tagify mixed input returns the JSON objects of selected tags and text in one single string, for example:
var tagify = new Tagify(myElement, {
mode: 'mix',
pattern: /#/,
whitelist: [{ value: "User Name", code: '$name' }, { value: "Phone Number", code: '$phone' }],
enforceWhitelist: true,
dropdown: {
maxItems: 20,
classname: "tags-look",
enabled: 0,
closeOnSelect: true
}
});
tagify.on('change', () => console.log(tagify.DOM.input.value))
The user input would be:
Hello User Name ร—, the SMS has been sent to your phone Phone Number ร—.
This simple example returns:
Hello [[{ value: "User Name", code: '$name' }]], the SMS has been
sent to your phone [[{ value: "Phone Number", code: '$phone' }]].
(and the JSON returned is escaped)
What I am doing later is replacing the tags that the user selected (by typing the # character and selecting them from the dropdown) with my own dynamic variables.
I was able to get a nice result with tagify.DOM.input.textContent as it rendered the following result:
Hello User Name, the SMS has been sent to your phone Phone Number.
However, since the whitelist is translatable and can be in other languages that I can't find and replace easily later, what I need is the code attribute from the JSON whitelist and not the value. The expected result that I couldn't find a way to reach yet is:
Hello $name, the SMS has been sent to your phone $phone.
Thanks.

You can create your custom transform function, to transform it the way you like, you can do something like this.
function transformer(value) {
return value.replace(/\[\[(.*?)\]\]/g, (arr => {
let json = JSON.parse(arr);
return json[0].map(e => e.code).join(', ');
}))
}
And then you can call it on change (or rather on/or before submit), like this:
tagify.on('change', (e) => transformer(e.detail.value));

Related

Tabulator field - Show Different Value

I would like to display field value as character, but underlying data as number, so when i do search query, i am able to utilize numeric data, instead of displayed data.
example
{ title: 'Plant' , field: 'plant.name'},
But required
{ title: 'Plant' , field [ex: search-column]: 'plant.id' , field [ex: display]:'plant.name' },
Ahhh. coming back to tabulator after long time, it totally skipped my mind ๐Ÿง .
here is the solution
{ title: 'Plant' , field: 'plant.id',
formatter:function(cell){
// This is eager loaded data in Laravel
return cell.getRow().getData().plant.title;
}
},
Now , in you query, you can search relationship with
->orWhereHas('plant', function($q) use($request){
$q->where('title','LIKE',"%$request->search%");
})
I hope this helps out others as well ๐Ÿ™‚

MS Teams adaptive card "herocard" not work on mobile

I`m creating bot for MS Teams and using JS Microsoft Bot Framework V4 SDK.
In my work, I use search message extension and to work with it, I implemented the onSelectItem method that returns a adaptive card. I will give an example of the code below.
return Promise.resolve({
type: "result",
attachmentLayout: "list",
attachments: [CardFactory.heroCard(
`${file.name}`,
`${text}`,
undefined,
CardFactory.actions([
{
type: "openUrl",
title: "Open",
value: `${openLink}`
},
{
type: "openUrl",
title: "Download",
value: `${downloadLink}`
},
]),
)]
});
Where I pass undefined, this should be the path to the picture, but in my implementation I don't need it. So and this code works great in the browser and on the desktop version here is a screenshot
however, on the mobile version, I get the following result
this is absolutely not the right card, it has no content or buttons
I think I found the answer myself. When the message extension search is triggered, the onQuery method is called and suppose you made a query and received an array of values โ€‹โ€‹that you want to display. And here, in the same method, iterating over the array, you must draw two cards at once. For example
files.forEach((file: IDocumentInfo): void => {
const card: any = CardFactory.heroCard(
cutString(file.name, LIMIT),
text,
undefined,
[
{
type: "openUrl",
title: "Open",
value: "", // some value
},
{
type: "openUrl",
title: "Download",
value: "" //some value,
},
]
);
const preview: any = {
contentType: "application/vnd.microsoft.card.thumbnail",
content: {
title: `${cutString(file.name, LIMIT)}`,
text: "", // some text
}
};
And here the variable preview in my case will respond to a small view of information after the search and the variable card will be responsible for the view after selection. And after the card is selected, the onSelectItem method is triggered, which I need to get more information about the document
It turns out that the adaptive heroCard is not to blame here, the onSelectItem method is not called in the mobile application, or I am doing something wrong

How to prevent alpaca from generating radio field when the search select has 3 or less options

I have a div and a following javascript:
let usersNotContributingIds = [ 19, 20, 21 ];
let usersNotContributingNames = [ "Flavius K.", "Pogchamp", "Lazy Gopnik" ];
let contributorToBeAddedId; // the value that will be used for further actions
$("#alpaca-search-contributing-users").alpaca({
data: null,
schema: {
type: "object",
enum: usersNotContributingIds,
},
options: {
name: "pls",
label: 'Contributor Fullname',
optionLabels: usersNotContributingNames,
helper: "Select user sou want to add as a contributor",
id: "select2-search",
focus: false,
events: {
change: function() {
console.log(this.getValue().value);
contributorToBeAddedId = this.getValue().value
},
focus: function() {
console.log(this.name);
},
blur: function() {
console.log(this.name + ": blur");
},
ready: function() {
console.log(this.name);
}
},
},
postRender: function(control) {
$('#select2-search').select2();
}
});
Obviously, I want to get the newly set value, or anyhow access the selected value and use it. For example with AJAX and a button.
The problem is, that when I have 3 or less options, Alpaca render the field not as a search, but as a radio-something and the this.getValue() is null.
Is there a way to force Alpaca to NOT USE THE RADIO BUTTONS? I dont want to use them, even if I had only 1 option. Documentation just promtly states, that if there are 3 or less options, it will generate radio buttons instead of select, but it says nothing about the fact, that it breaks everything and that I would not be able to retrieve the value the same way as with select field.
If I am doing something inefficiently or wrong, please tell me, I am new with Alpaca and I just want a neat select dropdown with search, that I can use to pick users from a list with any length. Also, I would like the "null" or "none" option to not be there.
To have your select component rendered you should use the option type and set it to "select".
The issue with the value is because you're using it wrong, to get the value in alpaca you only do this.getValue() and there's no need to add .value.
FYI: If you see the error "This field should have one of the values in Flavius K., Lazy Gopnik, Pogchamp. Current value is: 19" you should update your enum array to have strings instead of ints let usersNotContributingIds = [ "19", "20", "21" ];.
Here's a working fiddle for this.

JQuery validation only works on the first generated input

I'm trying to resolve this issue but no matter what I try (based on several suggestions solutions found here as well), I can never make it work.
I would like the Jquery validation plugin to validate automatically all the generated fields from a form. My problem is that it will only work on the first generated field; the validation of the subsequent ones will just be a duplicate of the first.
Here's the pertinent html code:
<form class="someFormClass" method="post">
<span>
<input class="calendarName" name="description" value="<?= value_from_php ?>">
<input class="calendarName" name="description" value="<?= value_from_php ?>">
</span>
</form>
And here's the jQuery validation code:
$(function () {
$('form').each(function () {
$(this).validate({
errorElement: "div",
rules: {
description: {
required: true,
remote: {
url: "calendar/calendar_available/",
type: "post",
data: {
name: function () {
return $(".calendarName").val();
}
}
}
}
},
messages: {
description: {
required: "Description field can't be blank !",
remote: "This calendar already exists."
}
}
});
});
So, as stated, the plug-in behaves properly for the first field. But if I check the values posted in Chrome's Network, the "name" key created in the jQuery validation will always send the value of the first input.
I tried many things (trying to implement on more level of ".each" method in the validation, trying to generate dynamically a specific id for each field to point on (instead of a class), trying to modify the plugin code as suggested here (How to validate array of inputs using validate plugin jquery), but it didn't work.
I think there's something I don't grasp about the logic here.
UPDATE :
So, one of the reasons of my problem is that jQuery validation absolutely requires input with different names. See : Jquery Validation with multiple textboxes with same name and corresponding checkboxes with same name
So, I made a script to generate a different name for each input with the intention to dynamically create validation rules based on those names, following this suggestion : https://stackoverflow.com/a/2700420/3504492
My validation script now look like this :
$(function() {
var rules = new Object();
var messages = new Object();
$('input[name*=description_]:text').each(function() {
var currentName = $("input[name="+this.name+"]").val();
rules[this.name] = {
description: {
required: true,
remote: {
url: "calendar/calendar_available/",
type: "post",
data: currentName
}
}
},
color: {required: true}
};
messages[this.name] = {
description: {
required: "Description field can't be blank !",
remote: "This calendar already exists."
},
color: {required: "Color field can't be blank !"}
};
});
$('form').each(function () {
$(this).validate({
errorElement: "div",
rules: rules,
messages: messages
});
}) });
This almost works. Almost because if I limit the rules et messages to the required keys, it will display the validation each field (if I add the specific name to the message string, it will display on the proper field). But with a most complex rule like mine (with a remote key containing various keys for instance), I get a " Cannot read property 'call' of undefined. Exception occurred when checking element , check the 'description' method." error in the Console.
My guess is that the "description" declaration in the "rules" definition should be dynamic too (the current "name" field being visited).
Any suggestion?

In MongoDB when searching with multiple parameters how to know which parameter matched

For example if I have a Mongoose schema with fields like title and body:
var Datum = db.model('Datum', {
title: { type: String },
body: { type: String },
}
Now I want to search both fields for a substring, I can do something like this:
Datum.find({
{ $or: [ { title: substring }, { body: substring } ] }
},
function(results) {
console.log(results)
})
but I'd like to give title a bigger weight, so for two entries, if one matched in title, another matched in body, I'd like the former to be returned in a higher order.
Is there anyway for mongoDB to return which condition matched in each result? Or do I have to search the database multiple times for this purpose?
when you create text indexes in MongoDB the default weight assigned to each indexed field is 1.
however if you want to give a particular field more weight you can include weights option when you create index and that will do the trick for you.
{
db.yourCollection.createIndex(
{
title: "text",
body: "text",
},
{
weights: {
title: 10,
body: 5
},
name: "myIndex"
}
)
}
afaik there is no function like match rate for non text indexes. (see satish chennupati answer for text index)
To cover that, mongo response need to be processed client side, to avoid expensive server calls, and depends on document number one check or loop need to be executed.

Categories