AndroidX itemTouchListener - androidx

I have just migrated a project to androidX and have managed to fix all teh issues except 1. which is the implimentation of the touch listener below.
private fun setItemTouchListner() {
val touchListner = object: ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
override fun onMove(recyclerView: androidx.recyclerview.widget.RecyclerView?, viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder?, target: androidx.recyclerview.widget.RecyclerView.ViewHolder?): Boolean {
return false
}
override fun onSwiped(viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder?, direction: Int) {
var rec: ChargeRecord? = null
if (viewHolder != null) {
rec = mAdapter?.getRecord((viewHolder.adapterPosition))
}
// delete record from cloud
if (rec != null) {
firebase?.child(rec.id)?.removeValue()
recordsViewModel?.deleteRecord(rec)
}
// remove record from list
if (viewHolder != null) {
records_list.adapter.notifyItemRemoved(viewHolder.adapterPosition)
}
}
}
val itemTouchHelper = ItemTouchHelper(touchListner)
itemTouchHelper.attachToRecyclerView(records_list)
}
I get an object is not abstract error and override does nothing error. I have searched around and tried to reformat the code but cant seem to fix it. Any guidance would be appreciated.
cheers

Ahhh
After alot of looking and pondering i finally worked out, i had to re-impliment the move and swipe methods.
this fixed the issue
cheers

Related

Javascript throws an “is undefined” error

I've been working with Javascript and recently I've been stucked with an error which I can't solve.
The Firefox console throws an "info[last] is undefined" error, and I've got no idea what is causing that. Here is the code, the line which provokes the trouble is number 7:
$("textarea").each(function() {
var id = $(this).parents("div.article").attr('id').split('_')[1],
kind = $(this).attr("class"),
text = $(this).val(),
last = info.length-1;
if(last !== 0) {
if(info[last].id == id) {
info[last].info.push([kind, text]);
}
} else {
object = {
id: id,
info: [[kind, text]]
};
}
info.push(object);
});
Hope you guys can help me figure it out.
How about:
$("textarea").each(function() {
var id = $(this).parents("div.article").attr('id').split('_')[1],
kind = $(this).attr("class"),
text = $(this).val(),
last = info.length-1;
if(last >= 0) {
//Check the index exists before accessing it - incase its null or similiar..
//Strictly speaking, we should test for the properties before we access them also.
if(info[last]) {
if(info[last].id == id) {
info[last].info.push([kind, text]);
}
}
} else {
object = {
id: id,
info: [[kind, text]]
};
info.push(object); //Also move this up.
}
});
I've moved a few things around, and changed the check for valid 'last'. Otherwise I've also added an if to double check that an object exists at that point in the array before trying to access it's properties.
If info is empty, last will be -1.
Change your if to
if(last !== -1) {
Also, you probably want to move
info.push(object);
inside the else.

What is a good name for this parameter?

What would be a good name for a parameter that controls what a function does? Currently I have been using ref, and have thought about using status instead but neither of those make sense.
Example:
function getItem(ref, key) {
if (ref == 1) {
return localStorage.getItem(key);
}
else if (ref == 2) {
return sessionStorage.getItem(key);
}
}
i vote for "switch". it's not pretty as Claire, but has a point too...
Since it's two different types of storages then why not name it type or storageType?

Aurelia: always call method in the view (problems after upgrade)

We've upgraded Aurelia (in particular aurelia-framework to 1.0.6, aurelia-bindong to 1.0.3) and now we're facing some binding issues.
There's a list of elements with computed classes, and we had a method int the custom element that contained the list:
getClass(t) {
return '...' +
(this.selected.indexOf(t) !== -1
? 'disabled-option' :
: ''
) + (t === this.currentTag
? 'selected-option'
: ''
);
}
And class.one-way="$parent.getClass(t)" for the list element, everything was OK.
After the upgrade it simply stopped to work, so whenever the selected (btw it's bindable) or currentTag properties were modified, the getClass method just wasn't called.
I partially solved this by moving this logic to the view:
class="${$parent.getClass(t) + (selected.indexOf(t) !== -1 ? 'disabled-option' : '') (t === $parent.currentTag ? 'selected-option' : '')}"
I know that looks, well... bad, but that made t === $parent.currentTag work, but the disabled-option class still isn't applied.
So, the question is:
How do I force Aurelia to call methods in attributes in the view?
P.S.
I understand that it might cause some performance issues.
Small note:
I can not simply add a selected attribute to the list element since I don't to somehow modify the data that comes to the custom element and I basically want my code to work properly without making too many changes.
UPD
I ended up with this awesome solution by Fabio Luz with this small edit:
UPD Here's a way to interpret this awesome solution by Fabio Luz.
export class SelectorObjectClass {
constructor(el, tagger){
Object.assign(this, el);
this.tagger = tagger;
}
get cssClass(){
//magic here
}
}
and
this.shown = this.shown(e => new SelectorObjectClass(e, this));
But I ended up with this (defining an extra array).
You have to use a property instead of a function. Like this:
//pay attention at the "get" before function name
get getClass() {
//do your magic here
return 'a b c d e';
}
HTML:
<div class.bind="getClass"></div>
EDIT
I know that it might be an overkill, but it is the nicest solution I found so far:
Create a class for your objects:
export class MyClass {
constructor(id, value) {
this.id = id;
this.value = value;
}
get getClass() {
//do your magic here
return 'your css classes';
}
}
Use the above class to create the objects of the array:
let shown = [];
shown[1] = new MyClass('someId', 'someValue');
shown[2] = new MyClass('someId', 'someValue');
Now, you will be able to use getClass property:
<div repeat.for="t of shown" class.bind="t.getClass">...</div>
Hope it helps!
It looks pretty sad.
I miss understand your point for computing class in html. Try that code, it should help you.
computedClass(item){
return `
${this.getClass(item)}
${~selected.indexOf(item) ? 'disabled-option': ''}
${item === this.currentTag ? 'selected-option' : ''}
`;
}
Your code not working cause you miss else option at first if state :/
Update:
To toggle attribute state try selected.bind="true/false"
Good luck,
Egor
A great solution was offered by Fabio but it caused issues (the data that was two-way bound to the custom element (result of the selection) wasn't of the same type as the input and so on). This definitely can be fixed but it would take a significant amount of time and result in rewriting tests, etc. Alternatively, yeah, we could put the original object as some property blah-blah-blah...
Anyway:
There's another solution, less elegant but much faster to implement.
Let's declare an extra array
#bindable shownProperties = [];
Inject ObserverLocator
Observe the selected array
this.obsLoc.getArrayObserver(this.selected)
.subscribe(() => this.selectedArrayChanged);
Update the shownProperties
isSelected(t) {
return this.selected.indexOf(t) !== -1;
}
selectedArrayChanged(){
for(var i = 0; i < this.shown.length; i++){
this.shownProperties[i] = {
selected: this.isSelected(this.shown[i])
}
}
}
And, finally, in the view:
class="... ${shownProperties[$index].selected ? 'disabled-option' : '')} ..."
So, the moral of the story:
Don't use methods in the view like I did :)

How do you iterate over the list of bodies from Box2D in emscripten?

I'm using the emscripten port of Box2D from here: https://github.com/kripken/box2d.js
It's working great, but I'm have some trouble interacting with emscripten.
Specifically I'm perform model-display sync in a loop like this:
function step() {
world.Step(1/60);
var body = this.world.GetBodyList();
while(body != null) {
readGeometry(body, body.data);
body = body.GetNext();
}
}
...but that doesn't seem to work. Although the C++ code returns NULL at the end of the linked list of body objects, body.GetNext() (return type in cpp is b2Body *) is never the native javascript null.
I've also tried:
body != Box2D.NULL
However, that is also never true. I'm guessing that emscripten is returning a wrapped pointer, and I have to do some specific operation on it to test for 'nullness'.
Inspecting the returned object I can see that the 'pointer' value in it for the null values is zero, and I can make it work with:
function step() {
world.Step(1/60);
var body = this.world.GetBodyList();
while(body.a != 0) { // <--------------- This hack
readGeometry(body, body.data);
body = body.GetNext();
}
}
So, it's clearly possible to test for NULL-ness, but I can't find any documentation on how to do it.
Try this
function step() {
world.Step(1/60);
var body = this.world.GetBodyList();
while(Box2D.getPointer(body)) { // <-- will equal 0 for a Box2D.NULL object
readGeometry(body, body.data);
body = body.GetNext();
}
}
I know this question is really old but I recently came across this problem and found the solution on github.
The accepted answer didn't work, but this did :
var next = World.m_bodyList;
var current;
while (next != null) {
current = next; next = next.m_next;
if(current.m_userData){
var current_body = {};
current_body.x = current.m_xf.position.x;
current_body.y = current.m_xf.position.y
}
}

How to add a custom validation rule to a model in Sencha Touch

This article by Sencha covers how to use the built in validation rules (presence, length, format, inclusion, exclusion) and mentions that adding custom rules is easy, but doesn't ever explain how to do it. I've googled high and low and read the sencha docs, but I can't find anything on how to do it. Any Ideas?
http://www.sencha.com/learn/using-validations-and-associations-in-sencha-touch
I think it's one of the slight errors in the documentation. I got them to work by adding some code
if (Ext.data) {
Ext.data.validations.custom = function (config, value) {
if (config && Ext.isFunction(config.fn)) {
//this should be the model
if (config.self) {
return config.fn.call(config.self, value);
} else {
return config.fn(value);
}
}
else
{
return false;
}
};
Ext.data.validations.customMessage = "Error";
}
Then to add a validation to a model, add an object to the model's validations array with type set to 'custom', e.g.
{
type: 'custom', field: 'SomeField', message: "Your field is bad",
fn: function (SomeFieldValueForThisInstance) {
//Add some validation code. The this pointer is set to the model object
//so you can call this.get("SomeOtherFieldToCheck")
//or any other instance method
//if the field is good
return true;
//else
return false;
}
}
Update: #salgiza was right, there's a few steps I forgot to mention in order to set the 'this' pointer correctly. If you look in the sencha touch code you'll see that at the end of Ext.data.Model's constructor it checks to see if there's an init function defined on the object, and if so, calls it
if (typeof this.init == 'function') {
this.init();
After you define your model you can add an init function to the prototype. In the function, iterate over the validations for the object and add a reference to this. This step should be done before any of the models are created.
YourModel.prototype.init = function () {
var i, len;
if (this.validations) {
for (i = 0, len = this.validations.length; i < len; i++) {
this.validations[i].self = this;
}
}
};
Then in the custom validation function above, just check if the config has a self pointer and if it does, call it with self. I've edited the code above to use self.
Note: I don't see the Model's init function documented, so if sencha gets rid of it, you'll have to add the this pointer to the model's validations some other way.
Sorry if this caused confusion for anybody.
I've slightly adapted the code from Jason for sencha touch 2 (since validations is now in the config property of the model). I suggest creating a base class from which all your other model classes would inherit. Then, once you've done that, you can use jason's technics for adding custom validations in Ext.data.validations singleton.
Ext.define('MyApp.model.CustomModelBase', {
extend: 'Ext.data.Model',
//adding an initializer to let custom validators access "self"
init : function () {
var i, len;
if (this.config.validations) {
for (i = 0, len = this.config.validations.length; i < len; i++) {
this.config.validations[i].self = this;
}
}
}
});
i think the easiest way to add complex custom validations to your model is to overwrite the validate method. see below, due to the parent call, it supports the builtin validation types.
validate: function() {
var me = this;
var errors = this.callParent(arguments);
/* custom complex validations here */
if(true !== me.get('checkOne') &&
true !== me.get('checkTwo') &&
true !== me.get('checkThree')) {
errors.add(Ext.create('Ext.data.Error', {
field : 'checkOne',
message: 'Choose at least one check, e.g. checkOne'
}));
}
return errors;
}
needed to implement a custom validation as well, googled, also found this tomalex0/SenchaTouch-Form-Validation on github

Resources