sencha touch :: how to handle long lists on iOS - iphone

in my sencha touch app I need to display a list of over 600 entries of objects per selected customer.
imagine one store holds some customers, displayed in a list. each of them has some "has-many"-related sub-stores, one holding about 600 objects (with urls, title, description...). these sub-info has to be listed when you select one customer from the first list.
the problem is on iOS you have to wait some seconds before the list is shown and it is very slow to scroll/use. it seems that it slows down the whole app.
are there any other options to display long lists, maybe like pagination ore something...
thnx!
edit: I found this article and will test these thoughts soon: Link
edit2: here we go: https://github.com/Lioarlan/UxBufList-Sench-Touch-Extension

You can paginate your list by adding a pageSize param to your store and the listpaging plugin to your list. By setting the autoPaging option, you can control whether the data is loaded automatically or on user click. Below is an example:
// store
Ext.regStore('BarginsStore', {
model: 'BarginModel',
autoLoad: true,
pageSize: 6,
clearOnPageLoad: false,
sorters: 'category',
getGroupString: function(record) {
return record.get('category');
}
});
// list
this.list = new Ext.List({
store: 'BarginsStore',
plugins: [{
ptype: 'listpaging',
autoPaging: true
}],
singleSelection: true,
emptyText: '<p class="no-bargins">No bargins found matching this criteria.</p>',
itemTpl: '<div class="bargin-record">{name}</div>'
});

are there any other options to display long lists, maybe like pagination ore something...
Pagination. Smartphones have far more limited CPU and RAM resources than a desktop PC. A six hundred row table with several elements is not going to display well on the devices on the market now. Hell, it'll probably slow down desktop browsers. Paginate it.

Related

How to Request Entries Automatically in x Seconds Intervals

In an XML view, I present a sap.m.Table with entries from an output ODataModel. Now the first 8 entries should be output for about 5 seconds and the remaining entries automatically reload, and switch in 5 second intervals, like a dashboard.
Here is an example: I have 30 entries.
At the beginning → Show entries 1 to 8.
After 5 seconds → Show entries 9 to 16.
After next 5 seconds → Show 17 to 24.
After next 5 seconds → Show 25 to 30.
Then repeat from the beginning.
Would you have any idea how I can do that? Could it possibly realized on the routing function with transfer of the required parameters to the URL?
I have made a Plunker to demonstrate how this can be achieved: Plunker Demo.
In a nutshell, you can leverage the startIndex and length parameters of the ManagedObject#bindAggregation method. More specifically, you use them to bind the table repeatedly.
this.byId("list").bindItems({
path: "/Meetups",
template: this.byId("template"),
templateShareable: true,
startIndex: start,
length: SLICE_SIZE
});
Because you continually rebinding the table, you can simply create the template object inside the XML view as a dependent, then you can access it via this.byId(...). We need to use the templateShareable flag to indicate that the template will be reused in further bindings (on the next tick).
<dependents>
<StandardListItem id="template" title="{Title}"
description="{Description}" counter="{MeetupID}" />
</dependents>
Regarding the routing, I made two routes: one initial ("default") route and one route which specifies the start index ("withStart"). Both of them pointing of course to the same view.
"routes": [{
"pattern": "",
"name": "default",
"target": "main"
}, {
"pattern": "/{start}",
"name": "withStart",
"target": "main"
}]
The transition between "slices" is done with the help of jQuery.sap.delayedCall. You can also use a IntervalTrigger instead, but it might cause some problems if the view is not the first one shown (as the first "slice" might not be shown for the full 5 seconds, depending of course on how you implement it).
jQuery.sap.delayedCall(INTERVAL, this, this.onTick, [start]);
Then a tick happens (i.e. when we need to change the "slice"), we simply do a navigation to the withStart route and increment the start index parameter. At this point, we can also check if we need to start from zero again (if the start index is greater than the total count).
start += SLICE_SIZE;
if (this.count && start >= this.count) {
start = 0;
}
this.getOwnerComponent().getRouter().navTo("withStart", {start: start});
In order to find out the total count (to be able to determine if you should go to zero), you can use the information from the List / Table's ListBinding.
var oBinding = this.byId("list").getBinding("items");
if (oBinding.isLengthFinal()) {
this.count = oBinding.getLength();
}
One problem that you might face in a multi-view application is that, if the user navigates between your "dashboard" view and some other view, the delayedCall might cause you to navigate back again to the "dashboard" view (i.e. the user might get "trapped" in the dashboard). To circumvent this, you could check to see if the view is visible first, before doing the navTo call.
Later edit:
For improving performance due to loading times you can use two different approaches:
Use the operation mode parameter when you are doing the binding. Setting it to Client will load all entries at once on the client side and the pagination mechanism will be done without further requests (at least in theory).
this.byId("list").bindItems({
path: "/Meetups",
template: this.byId("template"),
templateShareable: true,
startIndex: start,
length: SLICE_SIZE,
operationMode: OperationMode.Client
});
Do an initial load of the data using the ODataModel.read method, store the results into a JSON Model and then use the JSON Model for binding the list instead of the OData Model.
var oModel = this.getView().getModel("myJsonModel");
this.getView().getModel().read("/Meetups", {
success: function(oData) {
oModel.setData(oData);
}
});

Don't want to download all objects

I'm having a hard time understanding how I should structure my iOS app with regards to how Firebase works. I've got a few thousand users with my current implementation (not using firebase currently), but using .childAdded will give me all of the items in my db (of course to start with) but I'm trying to build something with .childAdded that allows me to say download the first 20 items, then as they scroll the tableview it downloads the next 20 items. My users post a lot of photos and their feed would be blown up with the amount of posts that .childAdded returns.
Thoughts on what to do?
This may help you better understand how to convert Firebase Queries into equivalent SQL Queries.
https://firebase.googleblog.com/2013/10/queries-part-1-common-sql-queries.html#paginate
// fetch page 2 of messages
new Firebase("https://examples-sql-queries.firebaseio.com/messages")
.startAt(2) // assumes the priority is the page number
.endAt(2)
.once('value', function(snap) {
console.log('messages in range', snap.val());
});
Here you can see the documentation that Explains Queries
You can go to the part that says limitToFirst.
For Example this says to limit to last 10:
var rootRef = firebase.database.ref();
var usersRef = rootRef.child("users");
var usersQuery = usersRef.limitToLast(10);
usersQuery.isEqual(usersRef); // false
usersQuery.isEqual(usersRef.limitToLast(10)); // true
usersQuery.isEqual(rootRef.limitToLast(10)); // false
usersQuery.isEqual(usersRef.orderByKey().limitToLast(10)); // false

Lets get the source of the photo using photo ID

I know that I could do something like below and get an array of images
FB.api('/{photo_id}/', function(res) { console.log(res) })
The widest image is just 720px. That's not very good for bigger screen developers and users. Any thoughts on how to get the original uploaded image
For example. Lets refer to the man himself Mar Zuckerberg
Get the cover using api
FB.api('/4/?fields=cover', function(res) { console.log(res) })
Now as you may see the returned cover is so low resolution and no good. Where as this is the result I'm expecting
https://scontent-lax1-1.xx.fbcdn.net/hphotos-frc3/t31.0-8/c0.93.1434.531/1275272_10101026493146301_791186452_o.jpg
Take a look at the images field, this will contain an array of the available sizes, the number and available sizes can vary based on the original size of the image though.
See https://developers.facebook.com/docs/graph-api/reference/photo for more details.

Dojo EnhancedGrid Scrolling with JsonRestStore

I am using a dojo 1.6 EnhancedGrid with a JsonRestStore as shown in the snippet below. I have about 15000 records of data. When the vertical scrollbar for the grid is dragged down in order to scroll, it takes a long time to get the data visible in the grid. After some debugging, I noticed that the single act of scrolling sends 4-5 GET requests to the server.
Is there a better way to solution this, or is there a way to insure that only the last GET request is sent to the server? I was able to capture the onscroll event, but wasn't sure how to prevent the GET request from being sent.
store = new dojox.data.JsonRestStore({
target:"myurl",
idAttribute: 'id',
allowNoTrailingSlash: true});
mygrid = new dojox.grid.EnhancedGrid({
id: 'mygrid',
queryOptions: {ignoreCase: true},
sortInfo: '3',
store: store,
structure: my.grid.structure,
selectionMode: "extended",
autoHeight: 12,
plugins: {indirectSelection: true},
fastScroll: false
},document.createElement('div'));
dojo.byId("datagrid").appendChild(mygrid.domNode);
// start the grid
mygrid.startup();
if you have that much information to handle i would suggest you to use the pagination-plugin for the enhanced Grid. The advantage is that only a certain number of data records will be loaded at once.
have a look here:http://dojotoolkit.org/reference-guide/1.8/dojox/grid/EnhancedGrid/plugins/Pagination.html#id2
Regards, Miriam

What metadata keys are available in Everyplay?

On the Everyplay Unity3D guide page these three lines are given as an example of using metadata with Everyplay.
Everyplay.SharedInstance.SetMetadata("level", levelNumber);
Everyplay.SharedInstance.SetMetadata("level_name", levelName);
Everyplay.SharedInstance.SetMetadata("score", score)
Are there any other metadata keys available than those three? Can you define your own metadata for your game instead of just using predefined keys? Could not find any more documentation on this than the above mentioned example.
You can and should provide as much metadata about the video as you can as there are several features to use the data already under work. The metadata supplied with the video has several intended (future) purposes. Currently only score and level_name are displayed with the videos on Everyplay (for example: http://everyplay.com/videos/8106 ).
The developer can (in the near future) configure what metadata to show with the videos, a racing game could show time, circuit and laps and an FPS game might show kills and deaths. Also we are already developing features into our API to allow developers to use the metadata to query existing videos, for example fetching a list of videos from level 1 in the past 10 days sorted by "score" and so on.
For a quick example here is the metadata that stair dismount (the video in the link above) provided with the same video:
metadata: {
somersaults: 1,
level: 60,
decapitation: false,
bifurcation: false,
push_force_z: -3957.182,
push_force_y: 1773.326,
distance: -1,
push_pos_z: 8.371746,
push_force_x: -1675.732,
push_pos_y: 24.18944,
push_body_name: "LeftForearm",
ragdoll_custom_face: true,
push_pos_x: -0.6025434,
push_body_id: 2189472344,
leaderboard_id: 1208019,
score: 3802645,
level_name: "Revolting Doors",
ragdoll_breakability: false,
distance_leaderboard_id: 0,
ragdoll_name: "Mr. Dismount",
ragdoll: 0
}