I have a text input for a card number. It should only contain numbers and has to be shown to the user as 4-digit blocks (example: 1234 5678 9123 4567).
My code successfully removes entered letters and creates the number blocks. The problem is that when I type a single non-digit key two times, that key shows up in the input once, seemingly ignoring the value converter. This does not happen when trying to type different letters in a row. Any third input will delete the letter as it should, but the problem does not disappear.
Using console.log, I can see that toView always returns the correct value. Is there any way to fix this? I tried adding ' pattern="^[\d ]*$" ' to the input but that does literally nothing.
Examples at the bottom.
Html:
<input type="text" id="cardNumber" class="form-control" placeholder="1234 5678 9123 4567"
value.bind="cardNumber | cardNumberFormat & validate" disabled.bind="isDisabled">
Javascript:
export class CardNumberFormatValueConverter {
toView(value) {
let cardNumberBlocks = this.createCardNumberBlocks(value);
if (cardNumberBlocks) {
return cardNumberBlocks.join(" ");
}
return "";
}
fromView(value) {
return value.split(" ").join("");
}
createCardNumberBlocks(value) {
if (!value) return "";
return value.match(/\d{1,4}/g);
}
}
Examples:
Typing : 123456 - Result : 1234 56 - Correct
Typing : 123456a - Result : 1234 56 - Correct
Typing : 123456a2 - Result : 1234 562 - Correct
Typing : 123456aa - Result : 1234 56a - Wrong
Typing : 123456aa2 - Result : 1234 562 - Correct
Typing : 123456ab - Result : 1234 56 - Correct
Typing : 123456aaa - Result : 1234 56 - Correct
Typing : 123456aba - Result : 1234 56 - Correct
Typing : 123456aa3bb - Result : 1234 563b - Wrong
Typing : 123456aabbb - Result : 1234 56b - Wrong
Related
I have a string value coming as "AH-0000006620, AH-0000006619, AH-0000006621", where I need to Remove the Prefix and the remaining numbers "0000006620, 0000006619, 0000006621" to be sorted in Ascending order and I want to store the sequence number for each of them like
for 0000006619 value to be 1
for 0000006620 value to be 2
for 0000006621 value to be 3
So that when I send the info to target system, while iterating the array, for the first element if it is 0000006620 then I will pass the value as 2 for the other sequence tag.
Please let me know how I can achieve this.
You can tweak this though this should serve as a good starting point to what you are looking for:
Script
%dw 2.0
import * from dw::core::Strings
output application/json
var inp = "AH-0000006620,AH-0000006619,AH-0000006621"
---
{((inp replace"AH-" with "") splitBy "," map ($ replace /^0+/ with "") orderBy $ map {
(leftPad($ as String,10,0)) : ($$)
})}
You can do it this way as well.
{((inp replace"AH-" with "") splitBy "," orderBy $ as Number map {
($) : ($$)
})}
**Output**
[
{
"0000006619": 0
},
{
"0000006620": 1
},
{
"0000006621": 2
}
]
let's assume that i have a table with columns such as:
ID SSID BSSID RSSI
1 abcd hs:hd:sd -60
2 abcd hs:hd:po -68
There are about 5000 records with the same SSID, slighltly different BSSID and the LEVEL values. My device is scanning the nearest environment for WiFi networks, therefore I know their MAC address and level of RSSI. I pick 3 with the highest value od RSSI.
First thing I would like to know if it is possible to search through the database to get all the records with the LEVEL value equal or close to 60, for instance 59,58,61.
Secondly, is there a way to query the database to return all the records with the same MAC addresses and RSSI values as from the 3 best scan result? If so, how would that query look like?
EDIT: Thanks for all the answers. What I'm trying to do now is to compare 3 scans with records stored in database with getRequiredData function. I would like to pass 2 parameters to this function, mac address and level and find records with same value for both parameters. The rawQuery seems to be fine, code is compiling but the app is crashing with the first scan. I cant find the cause of it, is it because my logic of getting these parameters is wrong or does it have something to do with query?
public Cursor getRequiredData(String mac, int level){
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("SELECT BSSID, RSSI FROM TABLE_NAME WHERE BSSID =? AND RSSI=?", new String[] {mac, level});
return res;
}
scan part:
class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
sb = new StringBuilder();
Comparator<ScanResult> comparator = new Comparator<ScanResult>() {
#Override
public int compare(ScanResult o1, ScanResult o2) {
return (o1.level>o2.level ? -1 : (o1.level==o2.level ? 0 : 1));
}
};
lista = wifiManager.getScanResults();
Collections.sort(lista, comparator);
for (int i = 0; i < lista.size(); i++) {
scanResult = wifiManager.getScanResults().get(i);
sb.append(new Integer(i + 1).toString() + ". " + (lista.get(i)).SSID + " " + (lista.get(i)).BSSID + " " + (lista.get(i)).level + "\n");
boolean isInserted = myDb.insertData(lista.get(i).SSID.toString(), lista.get(i).BSSID.toString(), lista.get(i).level);
if (isInserted = true)
Toast.makeText(MainActivity.this, "Data inserted", Toast.LENGTH_LONG).show();
else
Toast.makeText(MainActivity.this, "Data not inserted", Toast.LENGTH_LONG).show();
}
for (int i=0; i<4; i++)
{
scanResult = wifiManager.getScanResults().get(i);
match = myDb.getRequiredData(lista.get(i).BSSID.toString(), lista.get(i).level);
}
Log.i("match values: ", DatabaseUtils.dumpCursorToString(match));
txt.setText(sb);
wifiManager.startScan();
}
}
Here is what match contains:
2018-12-10 16:36:26.334 13347-13347/com.example.maciek.wifiscann I/match values:: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#e1a86d1
0 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
1 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
2 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
3 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
4 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
5 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
<<<<<
To get the 3 rows with the closest values to 60 in column LEVEL:
SELECT * FROM tablename ORDER BY ABS(LEVEL - 60), LEVEL LIMIT 3
For the 2nd part of your question, you should provide sample data of the table. Edit:
From the sample data that you posted I don't see a column RSSI, but if it exists in the table then the SELECT statement is ok.
Change the 2nd parameter of rawQuery() to:
new String[] {mac, String.valueOf(level)}
because level is int.
In onReceive() you use myDb. I don't know how you initialize it.
If the app crashes you must copy the log, the part that identifies the problem and post it.
First thing I would like to know if it is possible to search through
the database to get all the records with the LEVEL value equal or
close to 60, for instance 59,58,61.
SELECT * FROM your_table WHERE level BETWEEN 59 AND 61;
where your_table is the respective table name.
Note if levels are negative (as per example data) then BETWEEN requires the lowest value first so it would be BETWEEN -61 AND -59.
Secondly, is there a way to query the database to return all the
records with the same MAC addresses and RSSI values as from the 3 best
scan result? If so, how would that query look like?
SELECT * FROM your_table WHERE your_mac_address_column = 'the_mac_address_value' AND RSSI = 'the_rssi_value' ORDER BY LEVEL DESC LIMIT 3
Note the above assumes that the MAC address is stored in a column (if NOT then cannot be done unless the mac address can be correlated to a column).
Assumes best LEVEL is lowest so -1 is better than -60 (if not then use ASC instead of DESC)
Again your_table, your_mac_address_column, the_mac_address_value and the_rssi_value would be replaced accordingly with actual values (note that strings should be in single quotes).
in the following code (jsbin available here) I have two input elements, a range and a text, bound together via a computed property.
var vm = new Vue({
el: '#main-container',
data: {
sliderValue: 100,
},
computed: {
actualValue: {
get: function() {
if (this.sliderValue <= 100) {
return this.sliderValue;
} else {
return Math.round(this.sliderValue * 12.5 - 1150);
}
},
/* set won't work for val > 100*/
set: function(val) {
if (val <= 100) {
this.sliderValue = val;
} else {
this.sliderValue = Math.round((val + 1150)/12.5);
}
}
}
},
methods: {
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
<div id="main-container">
<input type="range" v-model="sliderValue" min=1 max=132>
<input type="text" v-model="actualValue">
<p>Slider: {{sliderValue}}</p>
<p>Actual: {{actualValue}}</p>
</div>
The range goes from 1 to 132, and its range is mapped [1..500] in the text input, with a simple transformation (basically it's a linear mapping with two different slopes for [1..100] and [101..132]) using the actualValue computed property.
Getting actualValue works as expected: dragging the slider correctly updates the input text with appropriate values in the range [1..500].
I'm not able to find a way to set actualValue, though. I'd like to be able to type a value in the text input, and make the slider's thumb update accordingly to the inverse transformation (val + 1150)/12.5.
It works as long as the typed number is in the range [1..100], but it "explodes" for numbers >100, e.g. 101 makes the sliderValue jump at 80892 and actualValue is then re-calculated as 1010000. As far as I understand, it's a looping-feedback scenario.
I've tried also alternative approaches (watch; v-on:change in the text input; using a third variable) to no avail.
Thanks in advance for any suggestion!
It's an amazing puzzle, and challenged me for a long time!
Look at the screenshot below. Your sliderValue and actualValue are strings, not integers. When you set actualValue as 101, you are actually setting it as a string value of "101"
Now, your sliderValue = ((actualValue + 1150)/12.5)
"101" + 1150 = "1011150" (another string!, try it in the developer console)
That messes up your entire calculation. Now you know how to fix it :-)
And you need to get that Vue devtools from here: https://github.com/vuejs/vue-devtools
EDIT: Response to comment #3
Here is the modified jsBin: http://jsbin.com/mahejozeye/1/edit?html,js,output
The only difference is introduction of two console.log statements in your map2 function. This helps you identify if your non-linear mapping function is working correctly or not. If you keep your developer console open, you will see what is happening in this function.
Case 1: When you set the value radius = 25 using the text box, your sliderRadius gets set to 111.55518394648828 and your radius again gets re-calculated as 25. So it comes around in a full circle and everything is stable here.
Case 2: When you set the value radius = 55, your sliderRadius gets set to 173.03607214428857 through your non-linear map2() function, which resets radius to 51.29869180420927
Clearly there is a circular dependency issue. Your sliderRadius and radius are very much dependent on each other and therefore radius is unable to take the value between 51 and 58.
You need to evaluate why it happens, as it has a lot to do with the non-linear mapping function that you have defined. The moment radius can take stable values at 55 (through the map2 function), then your current problem will be resolved.
The simplest fix is to set your input type to number:
<input type="number" v-model="actualValue">
or you can convert your value to an integer with something like:
set: function(val) {
var intVal = parseInt(val, 10);
if (!isNaN(intVal)) {
if (intVal <= 100) {
this.sliderValue = Math.max(1, intVal);
} else {
this.sliderValue = Math.min(132, Math.round((intVal + 1150) / 12.5));
}
}
}
I need each choice to have a label on two lines with a line break at a specific point in the String. I have put <br/> where I want the break but it is being escaped. How can I stop the value of the name field on my model from being escaped? The following code does not give me the result I want:
...
final RadioGroup<WebShippingMethodDO> rg =
initShipMethodOptionView(view, methodsModel, shipModel, shipMethodId, methods);
shipMethodForm.add(rg.setEscapeModelStrings(false));
...
The result is as follows:
...
<label for="shipMethodBtnac">FEDEX INTL ECONOMY<br/>(3 - 5 Days)</label>
...
But this is what I want:
...
<label for="shipMethodBtnac">FEDEX INTL ECONOMY<br/>(3 - 5 Days)</label>
...
How do I turn off the escaping?
...
final RadioGroup<WebShippingMethodDO> rg =
initShipMethodOptionView(view, methodsModel, shipModel, shipMethodId, methods);
// turn off escaping on rg's children
rg.visitChildren(new IVisitor<Component,Object>(){
#Override
public void component(Component child, IVisit<Object> visit)
{
child.setEscapeModelStrings(false);
}
});
shipMethodForm.add(rg);
...
I have a SQL query that is pulling back results ordered correctly when I try the query in MSSQL Studio.
I am using Datatables from Datatables.net and everything is working great apart from a sorting issue. I have some properties in the first column and I would like to order these like this:
1
1a
1b
2
3
4a
5
etc
However what comes back is something like this:
1
10
100
11
11a
I have looked though various posts but nothing seems to work and I believe that this must be something I should trigger from the datatables plugin but cannot find anything.
Could someone advise?
Your data contain numbers and characters, so they will be sorted as string by default. You should write your own plugin for sorting your data type. Have a look at here and here
to see how to write a plugin and how to use it with your table.
Edit: got some time today to work with the datatable stuff. If you still need a solution, here you go:
//Sorting plug-in
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
//pre-processing
"numchar-pre": function(str){
var patt = /^([0-9]+)([a-zA-Z]+)$/; //match data like 1a, 2b, 1ab, 100k etc.
var matches = patt.exec($.trim(str));
var number = parseInt(matches[1]); //extract the number part
var str = matches[2].toLowerCase(); //extract the "character" part and make it case-insensitive
var dec = 0;
for (i=0; i<str.length; i++)
{
dec += (str.charCodeAt(i)-96)*Math.pow(26, -(i+1)); //deal with the character as a base-26 number
}
return number + dec; //combine the two parts
},
//sort ascending
"numchar-asc": function(a, b){
return a-b;
},
//sort descending
"numchar-desc": function(a, b){
return b-a;
}
});
//Automatic type detection plug-in
jQuery.fn.dataTableExt.aTypes.unshift(
function(sData)
{
var patt = /^([0-9]+)([a-zA-Z]+)$/;
var trimmed = $.trim(sData);
if (patt.test(trimmed))
{
return 'numchar';
}
return null;
}
);
You can use the automatic type detection function to let the data type automatically detected or you can set the data type for the column
"aoColumns": [{"sType": "numchar"}]