Prevent the onTriggered event on listview header in blackberry 10 cascades? - blackberry-10

I have created the custom header in listview blackberry 10 qml. But the listview header also fired on OnTriggered event.
listItemComponents: [
ListItemComponent {
type: "header"
Container {
preferredWidth: 748
layout: DockLayout {}
Label {
text: "Custom Header"
horizontalAlignment: HorizontalAlignment.Left
verticalAlignment: VerticalAlignment.Center
textStyle{
base:SystemDefaults.TextStyles.BigText
}
}
}
}
]

Finally i found the answer, implement the listview ontriggered function like below
onTriggered: {
if(indexPath!=0){
var selectedItem = dataModel.data(indexPath);
var newPage = nextPage.createObject();
navigationPane.push(newPage);
}

Related

How to make fixed header availabel at the focus an focusable element?

I have a fixed header, when user scroll to an offset 100px, a class add to header to make it fixed:
fixed-header {
position: fixed:
top: 0,
left: 0,
right: 0,
width: 100%;
}
$( window ).on( 'scroll', function() {
if ( $( window ).scrollTop() >= 100 ) {
navigation.classList.add('.fixed-header');
document.body.style.paddingTop = "100px" // prevent page jump when fixed header
} else {
navigation.classList.remove('.fixed-header');
document.body.style.paddingTop = "0"
}
});
On top of page, when user focus a link via tab key, I use focus event listener to check the fixed class in DOM to scroll focusable element to re-position it below fixed header:
const elements = [...document.querySelectorAll(
"a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled])"
)];
header = document.body.querySelector('.header-top'); // Fixed header height: 100px
const handleFocus = (e) => {
console.log(header.classList.contains('.fixed-header')); // This will false
if (header.classList.contains('.fixed-header')) {
var windowScrollTop = $( window ).scrollTop(),
focusableScrollTop = $(e.target).offset().top;
if (focusableScrollTop - windowScrollTop < 100) {
window.scrollTo({ top: focusableScrollTop - 100, behavior: 'smooth' });
}
}
};
for (const element of elements) {
element.addEventListener('focus', handleFocus, { once: true });
}
But focus callback handler fire before DOM repaint (when fixed class added to header), so it can not detect fixed class in DOM:
Wrap focus handler inside requestAnimationFrame()', don't work, if I wrap focus handler inside setTimeout()' function with 300ms, it will detect correct fixed class, but cause page scroll jump (focusable element scroll up and down).
for (const element of elements) {
element.addEventListener('focus', setTimeout(() => {
handleFocus()
}, 300), { once: true });
}
Any way to make header.classList.contains('.fixed-header') come true at the focusable link focused?
I hope someone know this issue and help to fix this problem. Thank you very much.

GoldenLayout hide/show component (again)

I have an issue with showing/hiding a component similar to this question:
GoldenLayout, how to hide/show component?
My layout is as follows:
let config: Config = {
settings: {
showCloseIcon: false,
showPopoutIcon: false
},
content: [
{
type: 'column',
content: [
{
type: 'row',
height: 25,
content: [
{
title: 'A react component',
type: 'react-component',
component: 'searchContainer'
}
],
},
{
type: 'row',
height: 75,
content: [
{
title: 'A react component',
type: 'react-component',
component: 'leftContainer'
},
{
title: 'Another react component',
type: 'react-component',
component: 'rightContainer'
}
],
},
],
}],
};
I have a hideSearchBar and showSearchBar functions which look like this:
function hideSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
container.contentItems[1].config.height = 100;
container.contentItems[1].contentItems[0].config.height = 100;
container.contentItems[1].contentItems[1].config.height = 100;
container.config.height = 0;
container.contentItems[0].element.hide();
layout.updateSize();
//layout.updateSize($(window).width(), $(window).height());
}
function showSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
container.contentItems[0].element.show();
layout.updateSize();
}
The showSearchBar works perfectly and shows both rows of the grid correctly.
The hideSearchBar hides the top row correctly but leaves the second row does not take up the whole screen. I have tried setting the config.height to 100 in various places but cannot get it to work - there is a gap the size of the top row at the bottom of the screen.
Any help much appreciated.
I solved this with a different layout config where search bar was initially set to 0:
let config: Config = {
settings: {
showCloseIcon: false,
showPopoutIcon: false
},
content: [
{
type: 'column',
content: [
{
type: 'row',
height: 0,
content: [
{
title: 'A react component',
type: 'react-component',
component: LayoutComponent.SearchContainer
}
],
},
{
type: 'row',
height: 100,
content: [
{
title: 'A react component',
type: 'react-component',
component: LayoutComponent.WindowContainer
},
{
title: 'Another react component',
type: 'react-component',
component: LayoutComponent.CollectionContainer
}
],
},
],
}],
};
showSearchBar looks like this:
function showSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
if (searchRowHeight == 0) {
container.contentItems[0].config.height = SEARCH_HEIGHT;
}
else {
container.contentItems[0].config.height = searchRowHeight;
container.contentItems[1].config.height = containerRowHeight;
}
container.contentItems[0].element.show();
layout.updateSize();
}
and hideSearchBar looks like this:
function hideSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
container.contentItems[0].config.height = 0;
container.contentItems[1].config.height = 100;
container.contentItems[0].element.hide();
layout.updateSize();
}
In summary, the config made the searchBar hidden and when it was opened, heights were readjusted.
I use an event listener to check for height changes:
layout.on('stateChanged', () => {
let updateConfig: Config = layout.toConfig();
if (updateConfig.content[0].content[0].height != 0) {
searchRowHeight = updateConfig.content[0].content[0].height;
containerRowHeight = updateConfig.content[0].content[1].height;
}
HTH
Extending #jmc42's answer. Pretty good work-around but once thing it doesn't do is hide the splitter when expanding on pane to 100% and the collapsing the other to 0%.
As a work-around, I thought of 2 choices:
When the pane gets hidden, get the adjacent element representing the splitter bar within the same div and hide it.
When the pane gets hidden, and you detect a resize, always re-apply the expand the top pane to 100% and the bottom pane to 0%.
I opted for option 2 as it was simpler to implement and what I have is:
if (updateConfig.content[0].content[0].height != 0) {
searchRowHeight = updateConfig.content[0].content[0].height;
containerRowHeight = updateConfig.content[0].content[1].height;
}
else {
let container = gbl_Layout.root.contentItems[0].contentItems[0];
container.contentItems[0].config.height = 100;
container.contentItems[1].config.height = 0;
layout.updateSize();
}
My 'if' statement condition is more complex that the one above as I'm performing other checks but that will give you the gist of it. Works pretty well for me.

How to apply CSS to sap.m.table row based on the data in one of the cell in that row

I am working with sap.m.table. I have requirement to apply or change the background color for some of the rows based on the data in one of the column in those rows in table.
I am using the following code but it is not working
created the CSSfile: test.css
<style type="text/css">
.Total {
background-color: LightSteelBlue !important;
}
</style>
The above CSS file declare in Component.js like the following way ( correct me if this not right way to make the css file available to access in whole ui5 project.
"resources": {
"css": [
{
"uri": "css/test.css"
}
]
}
In Controller.i have defined the following method to apply the style sheet for the particular rows alone in table.
rowColours: function() {
var oController = this;
console.log("rowColours() --> Start ");
var oTable = this.oView.byId("tblAllocation");
var rows = oTable.getItems().length; //number of rows on tab
//start index
var row;
var cells = [];
var oCell = null;
for (i = 0; i < oTable.getItems().length; i++) {
//console.log("rowColours() :: row--> "+row);
//actualRow = oTable.getItems(); //content
if (i == 0) {
row = oTable.getItems()[i];
cells = cells.concat(oTable.getItems()[i].getCells());
//getting the cell id
oCell = cells[2];
oCell = oCell.toString().substring(29, oCell.length);
otemp = this.getView().byId(oCell).getText();
if (otemp.toString() == "TotalAllocation") {
oTable.getItems()[i].$().taggleClass("grandTotal");
}
}
}
console.log("rowColours() --> end ");
}
In the above method. I am checking the cell2 data ( in table cell 2 i was using the Textview control to display the data. when call this method to get the data in that cell. I am getting the following error.
otemp = this.getView().byId(oCell).getText());
error:
Uncaught TypeError: Cannot read property 'getText' of undefined
is the following code is possible to change the row bg color.
if (otemp.toString() == "TotalAllocation") {
oTable.getItems()[i].$().taggleClass("Total");
}
Please let me know how to change the bg color or applying the style for the perticular row in sap.m.table
Thanks
The approach your following is not right. Better you can use a formatter.
Example:
var oTable = new sap.m.Table({
columns: [
new sap.m.Column({
header: new sap.m.Label({
text: "Name"
}),
}),
],
items: {
path: 'modelList>/',
template: new sap.m.ColumnListItem({
cells: [
new sap.m.Text({
//formatter to the text property on sap.m.Text control.
text: {
parts: [{
"path": "modelList>Name"
}],
formatter: function(name) {
if (name == "TotalAllocation") {
// use this.getParent().. until u get the row. like this below and add class.
this.getParent().getParent().addStyleClass("Total");
}
}
}
})
]
})
}
});

How to get the list view row count in blackberry 10 cascades qml?

I need to get the no of rows in a list view blackberry 10 cascades qml? The list view data source model type is json. I have tried this
ListItem.initialized ? ListItem.view.dataModel.childCount(ListItem.indexPath) : 0
But its displaying only 0 even the list view row count is more than 1.
My code
dataModel: groupdatamodel
listItemComponents: [
ListItemComponent {
type: "header"
Container {
preferredWidth: 748
layout: DockLayout { }
Label {
text: "Title"
base: SystemDefaults.TextStyles.TitleText
fontWeight: FontWeight.Bold
}
}
Label {
id: subtitle
text: groupdatamodel.size() + "Items"
textStyle {
base: SystemDefaults.TextStyles.SmallText
fontWeight: FontWeight.Bold
}
}
]
Main.qml
import bb.cascades 1.0
import bb.data 1.0
Page {
content: Container {
Label {
text: "List View with json parsing"
}
ListView {
id: listViewDemo
dataModel: GroupDataModel {
grouping: ItemGrouping.None
}
listItemComponents: [
ListItemComponent {
type: "listItem"
StandardListItem {
title: ListItemData.ThumnailImage
description: ListItemData.CategoryID
}
}
]
function itemType(data, indexPath) {
return "listItem";
}
}
}
attachedObjects: [
DataSource {
id: serviceDataSource
source: "contacts.json"
type: DataSourceType.Json
onDataLoaded: {
listViewDemo.dataModel.clear();
listViewDemo.dataModel.insertList(data)
}
}
]
onCreationCompleted: {
serviceDataSource.load();
}
}
Contacts.json
[ {"CategoryID":"3","CategoryName":"News","CountryID":"1","Result":"OK"},
{"CategoryID":"4","CategoryName":"Daily Paper","CountryID":"1","Result":"OK"},{"CategoryID":"5","CategoryName":"Thanthi","CountryID":"1","Result":"OK"}, {"CategoryID":"1","CategoryName":"Newspaper","CountryID":"1","Result":"OK"},
{"CategoryID":"2","CategoryName":"Magazine","CountryID":"1","Result":"OK"}
]
main.cpp
add follwing lines in main file
#include <bb/data/DataSource>
#include <bb/data/JsonDataAccess>
Q_DECL_EXPORT int main(int argc, char **argv)
{
// We want to use DataSource in QML
bb::data::DataSource::registerQmlTypes();
4.FILENAME.PRO
LIBS += -lbbdata
DataModel::childCount(ListItem indexPath) returns the child count for the item in the list specified by indexPath, not the count of data items in the data model (and therefor available to the list). You need to interrogate the actual data model. For example GroupDataModel::size() returns the number of items in the GroupDataModel, similarly for QListDataModel.
I use this code in my project and it works fine:
console.log("pcs count" + pcsListModel.childCount(0));
Adding custom elements in label is not possible unless you use custom data model.
you can use:
your_groupdatamodel.size().toString();
or
your_groupdatamodel.childCount(0);
in javascript code.
J.

HTML Form to ExtJS Form

I have an html form in which the fields are extremely scattered. The page has been created using html table - rowspan and colspan combinations.
I need to convert this form to ExtJS and display it in a window.
After carrying out some research, I feel that table layout could be best choice for positioning the fields. But there are few issues which I have been facing as following:
If I give rowspan or colspan as 2 or more, then also the fields don't increase in size to occupy the availabe space and remain confined to single column.
If I resize the window, then the table doesn't resize (though, the form does as the tbar present at the top expand to occupy the complete space).
I have used the layout as 'fit' for window and layout as 'table' for the form.
I have also tried using 'anchor' layout for form and then having a fieldset with table layout, but the positioning didn't work.
Could someone please throw some light on this. Following is a basic code snippet I am using:
var form = Ext.create('Ext.form.Panel', {
url:'voyage_berth_monitoring.php',
fieldDefaults: {
labelAlign: 'right'
},
layout:{
type:'table',
columns:3
},
defaults:{
anchor:'100%'
},
tbar:[
{
xtype:'button',
text:'Clear'
},
{
xtype:'button',
text:'Delete'
},
{
xtype:'tbfill'
},
{
xtype:'button',
text:'Save'
},
{
xtype:'button',
text:'Exit'
}
],
items: [
{
fieldLabel:'item',
xtype:'textfield'
},
{
fieldLabel:'item',
xtype:'textfield',
colspan:2
},
{
fieldLabel:'item',
xtype:'textfield'
},
{
fieldLabel:'item',
xtype:'textfield'
},
{
fieldLabel:'item',
xtype:'textfield'
}
]
});
var win = Ext.create('Ext.window.Window', {
title: 'Window',
closable: true,
closeAction:'hide',
minimizable:true,
maximizable:true,
height:350,
width:750,
layout:'fit',
autoScroll:true,
items: form
});
win.show();
Basicly i had the same problem with the layout table, couldn't find any way to span my displayfields to the length of the td, and also the same issue with the 2 columns field.
The solution i prefered was to extend the table layout and give it that flexibility
Ext.define('Extended.TableLayout', {
alias:'layout.extendedTable',
extend: 'Ext.layout.container.Table',
type: 'extendedTable',
columns: 2,
rightMargin: 20,
tableAttrs:{
width: '100%'
},
tdAttrs:{
width:'50%'
},
itemCls:'x-table-cell',
renderItems: function(items) {
var totalWidth = this.getLayoutTargetSize().width,
len = items.length,
i, item, colNr;
for (i = 0; i < len; i++) {
item = items[i];
colNr = this.columns;
if ((colNr > 1) && Ext.isNumber(item.colspan)) {
colNr = colNr - item.colspan + 1;
}
item.width = Math.floor(totalWidth/colNr) - this.rightMargin;
}
this.callParent(arguments);
}
});
Using the extendedTable layout i get the desired look
One alternative it to serialize your HTML form data as JSON and load it into an EXT store. Once it's in a store, EXT will happily do whatever you want with it.