Dashcode mobile web app dynamic list row labeling - javascript

I'm trying to put together a mobile web app using Apple's Dashcode.
I would like to use a Rounded Rectangle List as a menu interface for my users, however, I cannot seem to change the various rows' labels in a dynamic list.
Here is the javascript for my list:
var dayController = {
/* categoryList will display these items */
_rowData: ["iPods", "Macs", "Applications"],
/* categoryListController must implement the numberOfRows and prepareRow functions */
/* This method is used to find out how many rows should be in the list */
numberOfRows: function() {
return this._rowData.length;
},
/* categoryList calls this method once for every row. */
prepareRow: function(rowElement, rowIndex, templateElements) {
/*
templateElements contains references to all elements that have an id in the category template row.
We use the lines below to update the list with each category item in _rowData.
*/
if (templateElements.categoryLabel) {
templateElements.categoryLabel.innerText = this._rowData[rowIndex];
}
/* Assign an onclick handler that will cause the browser to go a page
showing all products related to this category item, when clicked
*/
var self = this;
var handler = function() {
/* Get the category item associated with this row */
var category = self._rowData[rowIndex];
};
rowElement.onclick = handler;
}
};
I want to be able to assign the rowData[] as the labels for the rows in the lists, but I can't seem to get it to work.
I'm guessing I need to change something with the prepareRow function, right?
Has anyone successfully used JQuery with Dashcode to build a web app? Perhaps that would be a better approach.

Erm wouldn't you set the rounded rectangle in the css and not the javascript?
You can use Dashcode to make the web app but there other alternatives, rather a lot these days actually. However there was a JS framework called JQTouch, built on top of JQuery for doing this. JQTouch has now beed subsumed into Extjs and all of it rename Sechcha Touch. I would suggestyou go an look at that as a more flexible alternative.
I found Dashcode excellent for building Mac Widgets but much more limited for web based iPxx apps.

Related

Can I have expanded one node only on load in Tabulator.js?

I am using nested data trees in Tabulator.js and if I use the option dataTreeStartExpanded:true all nested rows will be expanded. I want only one be expanded on load/render? Is that possible?
Here is working jsFiddle to play around.
I found that there is a div with class tabulator-data-tree-control-expand or tabulator-data-tree-control-collapse. Changing the name in dev tools does nothing.
Currently it looks like
But I want to be like that after the web page loads
Maybe I can somehow click the + to expand. Tabulator has a listener there
But I do not know how to call it for that particular +.
oh, I found it in documentation.
.. a function that will be passed in a row component and the level of that row in the table (starting at 0), it should return a boolean value to indicate the rows expansion state:
var table = new Tabulator("#example-table", {
dataTree:true,
dataTreeStartExpanded:function(row, level){
return row.getData().driver; //expand rows where the "driver" data field is true;
},
});
and then in data you have to use new property driver:true

How to create a snappy User Interface with lots of local data?

I have a JSON file with 15000+ items. My JSON file has about 7MB. I'd like to display all results in a table (without pagination) and add a few checkboxes to display or hide the items under certain conditions. To simplify as much as possible, let's say I have a checkbox to display items from Paris only:
The problem is that the UI is not smooth. Clicking on the checkbox takes about one second to refresh the table. It's unacceptable.
I'm using fetch() to download JSON data and then keep it locally. When user clicks on the checkbox, here's what I did:
document.getElementById('paris-only').addEventListener('click', updateTable);
function updateTable() {
const parisOnly = document.getElementById('paris-only').checked;
items.forEach(item => item.visible = !parisOnly || item.city === 'Paris');
refreshTable();
}
function refreshTable() {
[...document.getElementById('items-table').children].forEach((tr, index) => {
tr.classList.toggle('hidden', !items[index].visible);
});
}
.hidden {
display: none;
}
I tried to play with setTimeout(_, 0), but it doesn't help much. It makes the UI freeze less, but it still takes a lot of time to refresh the table.
Is there any strategy available to make such an interface snappy? One of my ideas was to consider <canvas>, which makes drawing many elements quick, but it doesn't seem very natural for the task.
Another option would be to load data with fetch() on scroll, but I'd like to have all data loaded just once if possible.
What else should I consider?
I'd recommend using classes to signify if a given node should be shown or hidden (e.g. every node with name !== 'Paris' is in the notparis class. You can use javascript to initialize these categories (How do I add a class to a given element?) when you fetch the JSON table, and then showing/hiding can use for (tr of document.getElementsByClassName('notparis')) tr.visible = !parisOnly. If these categories overlap (i.e. you want notparis and notcoldweather), you could probably record which classes are currently visible or hidden and use document.getElementsByClassName('notparis notcoldweather') (this may be a bit more complex, but should maintain performance).
Also, changing the items directly instead of using an intermediate list might be more performant.

my reactjs button design feels slow onTouch on tablet vs tablet buttons

I built a web app that is viewed on tablets. It was made with reactjs and a express backend. It's a relatively small app that simple in that it just display items and allows users to customizer order items and such.
This was my attempt to create a custom 'check box' style button.
I have an array of items var items = ['ab','bc','cd','de','ef','fg','gh','hi','ij'] that can at times have about 30 elements total.
I create another array to list my items by pushing each elements in as li blocks
var itemsList = ;
items.forEach(item => {
toppingsList.push (
<li className={(this.checkChosen(item) === item) ? 'itemChosen' : 'itemNotChosen'} onClick={(e)=>{this.handleItemClicked(item)}}><p>{item}</p></li>
)
})
From here I create those <li></li> where checkChosen(item) checks if the topping is inside the 'selected pile'. The handleItemClicked(item) pushed an item into this components state.
this.state = {
itemsChosen = [];
}
It also checks to see if it's within the itemsChosen state and either adds or removes it.
I run this on a Lenovo tab 10 on a local host and it seems like these buttons have a delay, as if the onClick isn't very responsive. I used a similar method for a pin pad design.
I thought this could be an issue with the tablet but when I invoke the native keyboard for the pin pad (just an input type = "number" ) it feels quick, and smooth how you would expect the web app to run.
This method doesn't seem to be very demanding, but is it?

Access rendered items

Playing around with Slickgrid. But got some questions that I'm not figurate out.
I have made an Regex filter on two X cells, and it works surprisingly well.
But for every time you filter or make other actions i want to flash all incorrect fields with cellFlash or highlighter.
Atm i have made a formatter with same regex as filter uses but it seems not 100% correct.
The problem when i'm using cellFlash is that it trigger the animation on ALL rows not only the rows thats rendered.
I'm not sure that i'm triggering the flashcell on correct callback/stage, I did it on my filter function i saved all incorrect rows in an array then i loop them throught and trigger flash.
So is it possible to get all items thats rendered in Viewport? Haven't find any information about this. Only data i can get out from getRenderedViewport.. is pxls. getRenderedRange() or getViewport()..
If you need to do processing on each data item in the current slick grid viewport, you can use getRenderedRange() to get the range of data item indexes that are rendered. You could then use that to get each visible data item
function forEachItemInViewport(fn) {
var range = slickGrid.getRenderedRange();
var bottom = range.bottom;
while(bottom--) {
var dataItem = slickGrid.getDataItem(bottom);
fn(dataItem);
}
}
forEachItemInViewport(function (item) {
// do your work on each item in viewport
});

How to update ZK Grid values from jQuery

I have three Tabs and in each tab, I have a Grid.
The data for each Grid is coming from a database, so I am using rowRenderer to populate the Grids. The following code is common for all three Grids:
<grid id="myGrid1" width="950px" sizedByContent="true" rowRenderer="com.example.renderer.MyRowRenderer">
The rows are constructed from Doublebox objects. The data is populated successfully.
The Problem:
I need to handle multiple-cell editing on the client side. The editing is done via mouse-clicking on a particular cell and entering a value.
As example let's say that the user edits first cell on the first row and the value should be
propagated to all other cells on the same row and in all three Grids (so also the two Grids which the user currently does not see, because they are in tabpanes).
I am using jQuery to do this value propagation and it works OK.
I am passing the jQuery as follows:
doublebox.setWidgetListener(Events.ON_CHANGING, jQuerySelectors);
doublebox.setWidgetListener(Events.ON_CHANGE, jQuerySelectors);
This makes it possible to change the value in 1 cell and the change is instantly (visually) seen in all other cells filtered by jQuery selectors.
The problem is that the value is visually distributed to all the cells, but when I try to save the Grid data back to the database, the background values are the old ones.
I am assuming that ZK-Grid component is not aware that jQuery changed all the cell values. Nevertheless if I manually click on a cell that already has the NEW value (enter/leave/change focus) when I save the grid the NEW value is correct in that particular cell. Maybe that's a hint how can I resolve this.
Code of how I extract the Grid values:
Grid tGrid = (Grid) event.getTarget().getFellow("myGrid1");
ListModel model = tGrid.getModel();
MyCustomRow tRow = (MyCustomRow)model.getElementAt(i);
The model for my Grid is a List of MyCustomRow:
myGrid1.setModel(new ListModelList(List<MyCustomRow> populatedList));
I have a couple of assumptions, but whatever I have tried, hasn't worked. I have in mind that jQuery events and ZK-Events are different and probably isolated in different contexts. (Although I have tried to fire events from jQuery and so on..)
Do you have any suggestions? As a whole is my approach correct or there's another way to do this? Thanks for your time in advance!
Your problem is exactly what you are expecting.
Zk has it's own event system and do not care about your jq,
cos it's jq and zk don't observ the DOM.
The ways to solve your problem.
Use the "ZK-Way":
Simply listen at server-side and chage things there.
I am not sure if not selected Tabs
are updateable, but I am sure you could update the Grid
components on the select event of the Tab.
Fire an zk-event your self:
All you need to know, is written in the zk doc.
Basically, you collect your data at client side, send
an Event to the server via zAu.send() extract the
data from the json object at serverside and update your Grids
I would prefer the first one, cos it's less work and there should not be
a notable difference in traffic.
I post the solution we came up with:
This is the javascript attached to each Doublebox in the Z-Grid
//getting the value of the clicked cell
var currVal = jq(this).val();
//getting the next cell (on the right of the clicked cell)
objCells = jq(this).parents('td').next().find('.z-doublebox');
// if there's a next cell (returned array has length) - set the value and
// fire ZK onChange Event
if (objCells.length) {
zk.Widget.$(jq(objCells).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCells).attr('id')).fireOnChange();
} else { //otherwise we assume this is the last cell of the current tab
//So we get the current row, because we want to edit the cells in the same row in the next tabs
var currRow = jq(this).parents('tr').prevAll().length;
//finding the next cell, on the same row in the hidden tab and applying the same logic
objCellsHiddenTabs = jq(this).parents('.z-tabpanel').next().find('.z-row:eq(' + currRow + ')').find('.z-doublebox');
if (objCellsHiddenTabs.length) {
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).fireOnChange();
}
}
The java code in the RowRenderer class looks something like this:
...
if (someBean != null) {
binder.bindBean("tBean", someBean);
Doublebox box = new Doublebox();
setDefaultStyle(box);
row.appendChild(box);
binder.addBinding(box, "value", "tBean.someSetter");
...
private void setDefaultStyle(Doublebox box) {
box.setFormat("#.00");
box.setConstraint("no negative,no empty");
box.setWidth("50px");
String customJS = ""; //the JS above
//this is used to visually see that you're editing multiple cells at once
String customJSNoFireOnChange = "jq(this).parents('td').nextAll().find('.z-doublebox').val(jq(this).val());";
box.setWidgetListener(Events.ON_CHANGING, customJSNoFireOnChange);
box.setWidgetListener(Events.ON_CHANGE, customJS);
}
What is interesting to notice is that ZK optimizes this fireOnChange Events and send only 1 ajax request to the server containing the updates to the necessary cells.

Categories

Resources