In my firebase, the recently or last added data has to be ubsent all the time from my table. So I want to populate the table with all the data except for the recently added data. I mean to say I have data1, data2, data3, data4. I want only data1 to 3, and 4 should be ignored. I thought I could use something like limitToFirst(-1) could work, unfortunately it doesnt.
this is my line of code: var database = firebase.database().ref().child('Sales/JBC');
I tried: var database = firebase.database().ref().child('Sales/JBC').limitToFirst(-1);
Assuming you are certain that the data/node/key that you do not want to retrieve is always at the bottom., the trick you would need to use is, first know how man data you have, there are so many ways of getting count of data. Once you have the count you can use limitToFirst() method. So you say: if you want to ignore the last child, go like this: limitToFirst(count-1). This means if you have 20 elements, you need the first 19, so get count of elements (thus 20) then subtract 1. If you want up to 18 elements you subtract 2. And so on...
I think you may be looking for limitToLast(3). You will need to know how many items you want to retrieve though, as Firebase has no way to determine that for you.
Related
I am using tabulator package 4.3.0 to work on a webpage. The table generated by the package is going to be the control element of a few other plots. In order to achieve this, I have been adding a dataFiltered function when defining the table variable. But instead of getting the order of the rows in my data object, I want to figure a way to get the index of the rows in the filtered table.
Currently, I searched the manual a little bit and have written the code analogue to this:
dataFiltered: function(filters,rows){
console.log(rows[0]._row.data)
console.log(rows[0].getPosition(true));
}
But the getPosition always returned -1, which refers to that the row is not found in the filtered table. I also generated a demo to show the real situ when running the function. with this link: https://jsfiddle.net/Binny92/3kbn8zet/53/.
I would really appreciate it if someone could help me explain a little bit of how could I get the real index of the row in the filtered data so that I could update the plot accordingly and why I am always getting -1 when running the code written in this way.
In addition, I wonder whether there is a way to retrieve the data also when the user is sorting the table. It's a pity that code using the following strategy is not working in the way I am expecting since it is not reacting to the sort action and will not show the information when loading the page for the first time.
$('#trialTable').on('change',function(x){console.log("Yes")})
Thank you for your help in advance.
The reason this is happening is because the dataFiltered callback is triggered after the rows are filtered but before they have been laid out on the table, so they wont necessarily be ready by the time you call the getPosition function on them.
You might do better to use the renderComplete callback, which will also handle the scenario when the table is sorted, which would change the row positions.
You could then use the getRows function passing in the value "active" as the first augment return only rows that have passed the filter:
renderComplete: function(){
var rows = table.getRows("active");
console.log(rows[0].getPosition(true));
}
On a side note i notice you are trying to access the _row property to access the row data. By convention underscore properties are considered private in JavaScript and should not be accessed as it can result in unstable system behaviour.
Tabulator has an extensive set of functions on the Row Component to allow you to access anything you need. In the case of accessing a rows data, there is the getData function
var data = row.getData();
I want to query object from Parse DB through javascript, that has only 1 of some specific relation object. How can this criteria be achieved?
So I tried something like this, the equalTo() acts as a "contains" and it's not what I'm looking for, my code so far, which doesn't work:
var query = new Parse.Query("Item");
query.equalTo("relatedItems", someItem);
query.lessThan("relatedItems", 2);
It seems Parse do not provide a easy way to do this.
Without any other fields, if you know all the items then you could do the following:
var innerQuery = new Parse.Query('Item');
innerQuery.containedIn('relatedItems', [all items except someItem]);
var query = new Parse.Query('Item');
query.equalTo('relatedItems', someItem);
query.doesNotMatchKeyInQuery('objectId', 'objectId', innerQuery);
...
Otherwise, you might need to get all records and do filtering.
Update
Because of the data type relation, there are no ways to include the relation content into the results, you need to do another query to get the relation content.
The workaround might add a itemCount column and keep it updated whenever the item relation is modified and do:
query.equalTo('relatedItems', someItem);
query.equalTo('itemCount', 1);
There are a couple of ways you could do this.
I'm working on a project now where I have cells composed of users.
I currently have an afterSave trigger that does this:
const count = await cell.relation("members").query().count();
cell.put("memberCount",count);
This works pretty well.
There are other ways that I've considered in theory, but I've not used
them yet.
The right way would be to hack the ability to use select with dot
notation to grab a virtual field called relatedItems.length in the
query, but that would probably only work for me because I use PostGres
... mongo seems to be extremely limited in its ability to do this sort
of thing, which is why I would never make a database out of blobs of
json in the first place.
You could do a similar thing with an afterFind trigger. I'm experimenting with that now. I'm not sure if it will confuse
parse to get an attribute back which does not exist in its schema, but
I'll find out, by the end of today. I have found that if I jam an artificial attribute into the objects in the trigger, they are returned
along with the other data. What I'm not sure about is whether Parse will decide that the object is dirty, or, worse, decide that I'm creating a new attribute and store it to the database ... which could be filtered out with a beforeSave trigger, but not until after the data had all been sent to the cloud.
There is also a place where i had to do several queries from several
tables, and would have ended up with a lot of redundant data. So I wrote a cloud function which did the queries, and then returned a couple of lists of objects, and a few lists of objectId strings which
served as indexes. This worked pretty well for me. And tracking the
last load time and sending it back when I needed up update my data allowed me to limit myself to objects which had changed since my last query.
I don't think this is strictly infinite scrolling but it was the best i could think of that compares to what i am seeing.
Anyway, we are using ng-grid to show data in a table. We have roughly 170 items (rows) to display. when we use ng-grid it creates a repeater. When i inspect this repeater from the browser its limited to 35 items and, as you scroll down the list, you start to lose the top rows from the dom and new rows are added at the bottom etc (hence why i don't think its strictly infinite scrolling as that usually just adds more rows)
Just so I'm clear there is always 35 'ng-repeat=row in rendered rows' elements in the dom no matter how far you have scrolled down.
This is great until it comes to testing. I need to get the text for every item in the list, but using element.all(by.binding('item.name')) or by.repeater or by.css doesn't help as there is only ever 35 items present on the page.
Now to my question, how can i make it so that i can grab all 170 items as an object that i can then iterate through to grab the text of and store as an array?
on other pages where we have less than 35 items iv just used the binding to create an object, then using async.js to go over each row and get text (see below for an example, it is modified extract i know it probably wouldn't work as it is, its just to give you reference)
//column data contains only 35 rows, i need all 170.
var columnData = element.all(by.binding('row.entity.name'))
, colDataTextArr = []
//prevOrderArray gets created elsewhere
, prevOrderArray = ['item1', 'item2'... 'item 169', 'item 170'];
function(columnData, colDataTextArr, prevOrderArray){
columnData.then(function(colData){
//using async to go over each row
async.eachSeries(colData, function(colDataRow, nRow){
//get the text for the current async row
colDataRow.getText().then(function(colDataText){
//add each rows text to an array
colDataTextArr.push(colDataText);
nRow()
});
}, function(err){
if(err){
console.log('Failed to process a row')
}else{
//perform the expect
return expect(colDataTextArr).toEqual(prevOrderArray);
}
});
});
}
As an aside, I am aware that iterating through 170 rows and storing the text in an array isn't very efficient so if there is a better way of doing that as well I'm open to suggestions.
I am fairly new to JavaScript and web testing so if im not making sense because I'm using wrong terminology or whatever let me know and i'll try and explain more clearly.
I think it is an overkill to test all the rows in the grid. I guess it would be sufficient to test that you get values for the first few rows and then, if you absolutely need to test all the elements, use an evaluate().
http://angular.github.io/protractor/#/api?view=ElementFinder.prototype.evaluate
Unfortunately there is no code snippet in the api page, but it would look something like this:
// Grab an element where you want to evaluate an angular expression
element(by.css('grid-selector')).evaluate('rows').then(function(rows){
// This will give you the value of the rows scope variable bound to the element.
expect(rows[169].name).toEqual('some name');
});
Let me know if it works.
I have a long table with columns of schedule data that I'm loading via a form with jQuery load(). I have access to these html pages with the table data and can add classes/data attributes etc.
My form has select fields for hours and minutes (defaulting to the current time) and I'm trying to get the next closest time plus the four after that.
The time data in my tables are all formatted as <td>H:MM</td>.
Ideally with jQuery, I was wondering how I can strip the table data of everything but those times. Alternatively, since I can reformat this data would I be making my life easier to format it a certain way?
Things I've tried - I am admittedly a novice at js so these things may seem silly:
Reading the first character of each cell and comparing it to the
selected hour. This is obviously a problem with 10, 11, 12 and is
really intensive (this is a mobile site)
Using a single time select field thenCreating an Array of each
column to compare with the selected time. Couldn't get this working
and also creates an issue with having to use a single select for
every time.
Basically looking for a little guidance on how to get this working short of, or maybe including, copying all the html tables into JSON format...
May as well post http://jsbin.com/ozebos/16/edit, though I was beaten to it :)
Basic mode of operation is similar to #nrabinowitz
On load, parse the time strings in some way and add to data on each row
On filter (i.e. user manipulates a form), the chosen time is parsed in the same way. The rows are filtered on row.data('time') >= chosen_time
The resulting array of elements limited to 5 (closest time plus four as OP requested) using .slice(0, 5)
All rows are hidden, these rows are displayed.
Some assumptions have been made, so this code serves only as a pointer to a solution.
I thought this was an interesting question, so I put together a jsFiddle here: http://jsfiddle.net/nrabinowitz/T4ng8/
The basic steps here are:
Parse the time data ahead of time and store using .data(). To facilitate comparison, I'm suggesting storing the time data as a float, using parseFloat(hh + '.' + mm).
In your change handler, use a loop to go through the cells in sequence, stopping when you find the index of the cell with a time value higher than your selected time. Decrement the index, since you've gone one step too far
Use .toggle(i >= index && i < index+4) in an .each() loop to hide and show the appropriate rows.
Here's how to do it on client side. This is just an outline, but should give you an idea.
// Create a sorted array of times from the table
var times = []
$('#mytable td').each(function(cell) {
times.push(cell.innerHTML);
});
times.sort();
// Those times are strings, and they can be compared, e.g. '16.30' > '12.30' returns true.
var currentTime = '12:30' // you probably need to read this from your select
var i = 0;
while (times[i] < currentTime || i=times.length) {
i++;
}
var closestTime = times[i];
var closestTimes = times.slice(i, i+4);
If you want to access not the times, but actually the cells containing the times, you can find them like this:
$('#mytable td').each(function() {
if ($(this).text() in closestTimes) {
// do something to that cell
}
})
I am using Greasemonkey/Tampermonkey to visit pages and make a change to a 100-element table based on what's on the current page.
Short term storage and array manipulation works fine, but I want to store the data permanently. I have tried GM_getValue/GM_setValue, GM_SuperValue, localStorage, and indexedDB, but I am clearly missing something fundamental.
Nothing seems to allow me to write the array into the permanent storage and then read it back into a variable where I can access each element, such that variablename[32] is actually the 32nd element in the table (Well, 33rd if you start counting at zero, which I do).
I need access to the entire 100-element table while the script is running, because I need to output some or all of it on the page itself. In the most basic case, I have a for loop which goes from 0 to 99, printing out the value of variablename[i] each time.
I have no predisposition to any method, I just want the frickin' thing to work in a Greasemonkey/Tampermonkey script.
Towards the top of the script I have this:
for (var i = 0; i <= 99; i++) {
currentData[i] = localStorage.getItem(currentData[i]);
}
The purpose of the above section is to read the 100 entries into the currentData array. That doesn't actually work for me now, probably because I'm not storing things properly in the first place.
In the middle, after modifying one of the elements, I want to replace it by doing this:
localStorage.setItem(
currentData[specificElementToChange], differentStuff);
The purpose of the above is to alter one of the 100 lines of data and store it permanently, so the next time the code at the top is read, it will pull out all 100 entries, with a single element changed by the above line.
That's the general principle.
I can't tell if what I'm doing isn't working because of some security issue with Firefox/Chrome or if what I want to do (permanently storing an array where each time I access a given page, one element changes) is impossible.
It's important that I access the array using the variable[element] format, but beyond that, any way I can store this data and retrieve it simply is fine with me.
I think you're going about this wrong. LocalStorage stores strings so the simplest way to store an array in LocalStorage is to stringify it into JSON and store the JSON. Then, when reading it back, you parse the JSON back into an array.
So, to read it in, you do this:
var currentData = JSON.parse(localStorage.getItem("currentData") || "[]");
To save your data, you do this:
localStorage.setItem("currentData", JSON.stringify(currentData));
Working demo: http://jsfiddle.net/jfriend00/6g5s6k1L/
When doing it this way, currentData is a variable that contains a normal array (after you've read in the data from LocalStorage). You can add items to it with .push(), read items with a numeric index such as:
var lastItem = currentData[currentData.length - 1];
Or, change an item in the array with:
currentData[0] = "newValue";
Of course, it's just a normal array, so you can use any array methods on it.