CoffeeScript: search for an object with specific property value - coffeescript

This is how to search for existence of value in array:
words = ["rattled", "roudy", "rebbles", "ranks"]
alert "Stop wagging me" if "ranks" in words
I am looking for similar elegance in searching for existence of object with specified property value:
words = [
{ id: 1, value: "rattled" },
{ id: 2, value: "roudy" },
{ id: 3, value: "rebbles" },
{ id: 4, value: "ranks" }
]
alert "Stop wagging me" if "ranks" in words.value
But the line at the bottom does not work.

If you want a 1-liner, you can do the following:
alert "Stop wagging me" if do -> return yes for w in words when w.value is 'ranks'
The advantage is that it will iterate in the array instead of deriving a new one (memory-efficient) and it will stop the iteration as soon as it finds a match (cpu-efficient). The price to pay is that it's perhaps a bit less readable. To address that, the best way might be to make your own utility function:
inObjectMember = (obj, key, value) ->
for o in obj when o[key] is value
return yes
alert "Stop wagging me" if inObjectMember words, 'value', 'ranks'

I just tried following and it worked for me:
alert "Stop wagging me" if "ranks" in (word.value for word in words)

Related

Swift Checklist - Saving the Switch Data for multiple Rows

So I have a Simple UITableView that will display a UILabel and a UISwitch. I need to be able to get the values of each switch update my object then eventually send the data the API. I has a semi working concept. But this only worked if ALL the cells were visible. Before I only had 5 items to be checked. So I could simply loop through everything and get the data. Now my checklist has grown to over 20 items.
I understand to a degree why the current code doesn't work. It finds nil values. That would be the cells that aren't visible.
My big question is how do i go about capturing the value of all the cells and the value of all the UISwitch values and update my object?
I tried to use the KVO method. This is what I have so far, I have never used this before and a bit lost:
private var observation: NSKeyValueObservation?
observation = switchCell.observe(\.switchOne, options: [.old, .new]) { value, change in
print("value: \(value.switchOne.isOn)")
print("change old: \(change.oldValue)")
print("change new: \(change.newValue)")
}
My issue is I am not sure what I am supposed to use for the key path. Iget the following warning:
Passing reference to non-'#objc dynamic' property 'switchOne' to KVO method 'observe(_:options:changeHandler:)' may lead to unexpected behavior or runtime trap
Then the simulator doesn't boot up. What is the easiest way/best way to do this? Like I said I have 2)+ items on my checklist as I completed each item, I turn the switch on. Then I need to get the value for each item, and update the object with the correct value. Then I send the data to the API to store the info to the database. From what I was reading this seemed to be the right direction.
store predefined status of switches in array of dictionary like:
let alreadyYouHaveThis = [["id": 1, "title": "name"...., ], [ "id": 1, "title": "name"....., ],["id": 1, "title": "name"...., ]
just add one more key in the same data like status...
let updatedData = [["status": true, "id": 1, "title": "name"...., ], ["status": true, "id": 1, "title": "name"....., ],["status": false, "id": 1, "title": "name"...., ]
now that status will be used in cellforindexpath method as other:
func cellforindexpath() ..... {
let status = data[indexPath.item]["status"]
swithc.tag = indexpath.item
setswitchstatus on above value
}
and action for switch :
#Objc func switchStatus(_ switch: UISwitch) {
let status = data[switch.tag]
status != status
data[switch.tag]["status"] = status
....
}
or can edit main data source and add these status in that data.
if you cant perform this let me know.

TinyMCE 5: Autocomplete that can be ignored so you can just type your own entry

I want to help the user author handlebars/mustache templates so when they type a { character, an autocomplete of known template values comes up to assist the user. But the user may not want to choose one of the suggested options, they might just want to continue typing a new template value and terminate it with a }. In the example in the code below, the options "Order Number" and "Delivery Date" are the known autocomplete options, but I want the user to be able to type {Invoice Number} for example.
I've succeeded in make this work in one way. As a user is typing {Invoice Number} I add it to the list of allowed options in the autocompleter fetch function. So the user can get what they want into the document if the click on the suggested option. Clicking fires the onAction function. I want onAction to fire as soon as the user types the closing handlebars character i.e. }.
Here is the code I have tried. I am using TinyMCE 5.
let template = (function () {
'use strict';
tinymce.PluginManager.add("template", function (editor, url) {
const properties = [
{value: "Order Number", text: "Order Number"},
{value: "Delivery Date", text: "Delivery Date"}
];
const insertNewProperty = function(value) {
let property = {value: value, text: value};
properties.push(property);
return property;
};
editor.ui.registry.addAutocompleter('autocompleter-template', {
ch: '{',
minChars: 0,
columns: 1,
fetch: function (pattern) {
return new tinymce.util.Promise(function (resolve) {
let filteredProperties = pattern ? properties.filter(p => p.text.indexOf(pattern) > -1) : properties;
if (filteredProperties.length > 0) {
resolve(filteredProperties);
} else {
resolve([{value: pattern, text: pattern}]);
}
});
},
onAction: function (autocompleteApi, rng, value) {
let property = properties.find(p => p.value === value);
if (!property) {
property = insertNewProperty(value)
}
let content = `{${property.text}}`;
editor.selection.setRng(rng);
editor.insertContent(content);
autocompleteApi.hide();
}
});
return {
getMetadata: function () {
return {
name: "Learning",
url: "https://stackoverflow.com"
};
}
};
});
}());
})();```
You can add a matches function to your callbacks, along with your onAction, this help you do it.
matches: function (rng, text, pattern) {
if(pattern.endsWith('}')){
pattern = pattern.replace('}', '');
/**
* Check if pattern does not match an existing
* variable and do what you want
*/
return true;
}
},
And make sure the function always returns true.

Find records where field ends with other field

I have title, director and englishTitle fields.
{
title: "Iron Man",
director: "Someone Important",
englishTitle: "Iron Man Someone Important"
}
I need to find all the records that have englishTitle ending with director's value.
How can I perform such query with MongoDB?
As described here, you can use regex : https://docs.mongodb.com/manual/reference/operator/query/regex/
In your case it would be
{ englishTitle: { $regex: /^.*director$/ } }
For finding the value of director, I suppose you can use "$where"
https://docs.mongodb.com/manual/reference/operator/query/where/
db.myCollection.find( function() {
var possibleDirector = this.englishTitle.substr(this.englishTitle.length - 1 - this.director.length);
return (possibleDirector === this.director);
} );
(maybe it would require little polishing like checking the length to not obtaint negative value in substr)

angularstrap typeahead with json object array is not working

I am using angularstrap typeahead directive. Its working fine with single object json values but its not working when replacing the json with my json object array.
Demo Json:
typeahead= ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia"];
<input type="text" ng-model="typeaheadValue" bs-typeahead="typeahead">
The above code is working fine.
My JSON object array:
typeahead = [
{id: 1, name: 'name1', email: 'email1#domain.com'},
{id: 2, name: 'name2', email: 'email2#domain.com'},
{id: 3, name: 'name3', email: 'email3#domain.com'}
];
$scope.typeaheadFn = function(query) {
return $.map($scope.typeahead, function(contacts) {
return contacts;
});
}
<input type="text" ng-model="typeaheadValue" bs-typeahead="typeaheadFn">
Please give me some solution for this.
You want to map your items to a list of strings, I believe.
Try:
$scope.typeaheadFn = function(query) {
return $.map($scope.typeahead, function(contact) {
return contact.name;
});
}
(I should add that I am currently stumped by something similar)
If you have, for example:
items = [
{id: 1, name: 'name1', email: 'email1#domain.com'},
{id: 2, name: 'name2', email: 'email2#domain.com'},
{id: 3, name: 'name3', email: 'email3#domain.com'}
];
You will need:
<input type="text" bs-typeahead ng-model="selectedItem" ng-options="item.name for item in items|orederBy:'name'|filter:{name:$viewValue}:optionalCompareFn"></input>
If you exclude filter from ng-options matching will be done on every property of item object, so if you want it to be done on one property add filter:{propName:$viewValue}. Also, if you exclude optionalCompareFn, default comparison from angular will be applied, but you can add your custom one (on your $scope), with signature (actual is property value of the item, stated in filter, not the whole object).
optionalCompareFn(expected,actual){ return /compare and return true or false/}
Attempt 1
I finally got this semi-working after a huge amount of frustration.
An easy way to get your desired text appearing is for each item to have a toString method.
You might have something like
typeaheadData = [
{id: 1, text: "abc", toString: function() { return "abc"; }},
{id: 2, text: "def", toString: function() { return "def"; }}
]
Then you will see the correct text in the options that popup, but the matching won't yet work properly (the items shown by the widget won't match the text the user enters in the box).
To get this working I used the new filter option that's been added in the current git version of angular-strap. Note that it's not even in the pre-built dist/angular-strap.js file in the repository, you will need to rebuild this file yourself to get the new feature. (As of commit ce4bb9de6e53cda77529bec24b76441aeaebcae6).
If your bs-typeahead widget looks like this:
<input bs-typeahead ng-options="item for item in items" filter="myFilter" ng-model="myModel" />
Then the filter myFilter is called whenever the user enters a key. It's called with two arguments, the first being the entire list you passed to the typeahead, and the second being the text entered. You can then loop over the list and return the items you want, probably by checking whether the text matches one or more of the properties of an item. So you might define the filter like this:
var myApp = angular.module('myApp', ['mgcrea.ngStrap'])
.filter('myFilter', function() {
return function(items, text) {
var a = [];
angular.forEach(items, function(item) {
// Match an item if the entered text matches its `text` property.
if (item.label.indexOf(text) >= 0) {
a.push(item);
}
});
return a;
};
});
Unfortunately this still isn't quite right; if you select an item by clicking on it, then the text parameter will be the actual object from the items list, not the text.
Attempt 2
I still found this too annoying so I made a fork of angular-strap (https://github.com/amagee/angular-strap) which lets you do this:
typeaheadData = [
{id: 1, text: "abc"},
{id: 2, text: "def"}
]
//...
$scope.myFormatter = function(id) {
if (id == null) { return; }
typeaheadData.forEach(function(d) {
if (d.id === id) {
return d.text;
}
});
};
<input bs-typeahead ng-options="item for item in items" ng-model="myModel"
key-field="id" text-field="text" formatter="myFormatter" />
With no need to fuss around with toString methods or filters. The text-field is what the user sees, and the key-field is what is written to the model.
(Nope! Still doesn't work if you update the model without going through the view).
The formatter option is needed so when you set the model value to just the key field, the widget can figure out the right text to display.

Why does Ext.form.ComboBox remove all the values automatically when selected any item in the list?

I've made a combo box and its working fine except when I select one of the items in the combobox, it removes all other values in it. Here is a piece of code:
var comboitemarray = new Array();
for(var comboitems=0;comboitems<listitems.length;comboitems++){
comboitemarray[comboitems] = listitems[comboitems].item;
}
dynamicformfield = new Ext.form.ComboBox({
id: fieldname,
fieldLabel: fieldlabel,
name: fieldname,
editable: false,
autoSelect : true,
store: comboitemarray,
queryMode: 'local',
});
Any idea? Or am I missing anything here?
You gave an Array as store :
store: comboitemarray
Where it expects an Ext.data.Store. Implement an Ext.data.ArrayStore() from that comboitemarray array . Check the documentation of ArrayStore and always test in firebug for the errors.
I behaves that way because it's not a select-box, it's a combo-box.
If you had the following items:
a
aa
aaa
and you selected "aa", there would then be two options in the box: 'aa', and 'aaa'.
If you think carefully about how you'd like it to work, you'll realize that to get what you want will break ability to have any sort of meaningful type-ahead functionality.