Using image and carousel on the same panel in sencha touch - layout

I am new in sencha touch and need to achieve this layout on a single simple page:
I need an image and below the image, there should be a carousel containing two another images which the user can swipe.
Here is my code:
Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function() {
// Create a Carousel of Items
var carousel1 = new Ext.Carousel({
defaults: {
cls: 'card'
},
items: [{
html: "<img src='teil1.jpg' width='320' height='60' alt='' border='0'>"
},
{
html: "<img src='teil2.jpg' width='320' height='60' alt='' border='0'>"
}
]
});
var panel = new Ext.Panel({
fullscreen: true,
html: "<img src='sport1_top.jpg' width='320' height='302'>"
});
new Ext.Panel({
fullscreen: true,
layout: {
type: 'vbox',
align: 'stretch'
},
defaults: {
flex: 1
},
items: [panel, carousel1]
});
}
});
The carousel and the panel containing the first image are displayed on the same portion of the page.
Am I missing something?
Thanks for your interest.
leon.

Removing the
fullscreen: true
from the sport1_top panel worked for me
Mark

This problem was nagging me too. After trying everything I could think of, what appears to help was to get rid of all of those fullscreen properties except on the main Ext.Panel, and use "layout:'fit'" on all of the cards, which I added to my defaults in the Ext.Carousel object.
var toolbar = new Ext.Toolbar({ title: 'testing', dock: 'top'});
var around = new Ext.Carousel({
ui: 'dark',
direction: 'horizontal',
defaults: { cls: 'card', layout:'fit' },
items: [
{ html: 'card 1'},
{ html: 'card 2'},
{ html: 'card 3'},
{ html: 'card 4'},
]
})
var panel = new Ext.Panel({
fullscreen: true,
layout: {
type : 'fit',
align: 'top'
},
defaults: {
flex: 1
},
items: [ around ],
dockedItems: [ toolbar ]
});
panel.show();

I believe you have to use layout: 'fit' for your Carousel (In your Panel, instead of vbox). Or you could make another panel SubPanel that has your vbox and that SUbPanel({layout: 'fit'});
I came across the same problem, I believe this works.
GL

Related

jTable dynamic custom toolbar item in child table

I have a jTable with a child table for each row. On the toolbar header of the child table I have added a custom toolbar item. I want to make that toolbar item dynamic in the sense that if there are already some rows I do not want it to show. I came across a very similar query for the main toolbar "add new" button which added a function to run on recordsLoaded:
Below is my first attempt - it is just the field entry for the main table that specifies the child table. However the ".find(....)" spec will not work in my case as mine is a custom toolbar item. What do I need to put as the .find criteria?
Thanks
Dance: {
title: '',
width: '4%',
sorting: false,
create: false,
listClass: 'centreCol',
display: function(book) {
var $img = $('<img src="Images/layers.png" title="Show associated dance entries" />');
//Open child table when user clicks the image
$img.click(function() {
var thisrow = $img.closest('tr'); //Parent row
if($('#BookTableContainer').jtable('isChildRowOpen',thisrow)) { // Clicking image a second time closes the child row
$('#BookTableContainer').jtable('closeChildRow',thisrow);
} else {
currentTitleID = book.record.DanceTitleID;
$('#BookTableContainer').jtable(
'openChildTable',
thisrow,
{
title: 'Related Dance',
toolbar: {
items: [
{
icon: 'Images/add.png',
text: 'New dance',
tooltip: 'Add dance details',
click: function() { CreateDanceDialog(); }
}
]
},
actions: {
listAction: 'BookPageData.php?action=listChildDances&DanceTitleID=' + currentTitleID,
// createAction: 'dancesData.php?action=createAssignment',
// deleteAction: 'dancesData.php?action=deleteAssignment'
},
recordsLoaded: function(event, data) {
var rowCount = data.records.length;
if (rowCount>0){
$('#BookTableContainer').find('.jtable-toolbar-item.jtable-toolbar-item-add-record').remove();
}
},
fields: {
DanceID: { key: true, create: false, edit: false, list: false, visibility: 'hidden' },
DanceTitleID: { type: 'hidden', defaultValue: currentTitleID },
ChoreographerID: { title: 'Choreographer', width: '40%', options: function() { return ChoreographerOptions; } },
FormationID: { title: 'Formation', width: '30%', options: function() { return FormationOptions; } },
GenreID: { title: 'Genre', width: '30%', options: function() { return GenreOptions; } }
}
},
function(data) { data.childTable.jtable('load'); }
);
}
});
//Return image to show on the person row
return $img;
}
},
Try this
$('#BookTableContainer').find('.jtable-toolbar').remove();

Multiselect search whole string

I have a multiselect with search bound to a store (with attribute string_value). Search only searches strings that start with "string to search" instead of contains "string to search" (similar to searching for '%string%' instead of 'string%'). Is there a way to do this by extending 'multiselector-search'?
Below is my multiselector control bound to a form:
var ms = Ext.widget('form', {
xtype: 'multi-selector',
width: 400,
height: 300,
requires: [
'Ext.view.MultiSelector'
],
layout: 'fit',
renderTo: Ext.getBody(),
items: [{
bbar: [{
xtype: 'button',
itemId: 'button',
html: 'Toolbar here',
text: 'Submit request to API',
// get submitted array
handler: function() {
if (cardioCatalogQT.config.mode === 'test') {
console.log('In submitted values handler: ');
}
var submitted = Ext.getCmp('test');
var dx = [];
Ext.Array.each(submitted.store.data.items, function (item) {
dx.push(item.data.string_value);
}); // each()
Ext.Msg.alert('Submitted Values',
'The following diagnoses will be sent to the server: <br
/>' + dx);
if (cardioCatalogQT.config.mode === 'test') {
console.log(dx);
}
}
}],
xtype: 'multiselector',
title: 'Selected Dx',
id: 'test',
name:'test',
fieldName: 'string_value',
viewConfig: {
deferEmptyText: false,
emptyText: 'No Dx selected'
},
// TODO: fix ability to remove selected items when box is unchecked
search: {
field: 'string_value',
store: 'Diagnoses'
}
}]
}).center();
The closest I could find to this problem was http://www.sencha.com/forum/showthread.php?240887. I tried making it work with the multiselect search with no success.
The MultiSelector uses the Ext.util.Filter to narrow the results based on the typed text. You need to enable the anyMatch property for it to match anywhere.
To do that, you'll have to include a new "search" function in your multiselector's search object that will have anyMatch=true.
Please see my fiddle, https://fiddle.sencha.com/#fiddle/jf5, for an example of how to do this.

Extjs tree not able to load nested object

I have a class called Zone1s in java which has 2 fields text(name of zone) and list of Zone1s.
when i convert it to json i get following response :
{"text":"Papa","Zone1s":[{"text":"Beta1","Zone1s":[{"text":"BetaBeta1","Zone1s":[]},{"text":"BetaBeta2","Zone1s":[]}]},{"text":"Beta2","Zone1s":[]}]}
i wrote a Extjs model,store and panel below:
Ext.define('Zone1s', {
extend: 'Ext.data.Model',
fields: [
{ name: 'text', type: 'string' }
],
proxy: {
type: 'ajax',
url : 'test.htm',
reader: {
type : 'json',
record: 'Zone1s'
}
},
hasMany: {model: 'Zone1s', name: 'Zone1s'},
belongsTo: 'Zone1s'
});
var store =Ext.create('Ext.data.Store', {
model: 'Zone1s',
autoLoad: true
});
Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 200,
height: 150,
store: store,
renderTo: Ext.getBody()
});
i am getting following error:
me.store.getRootNode is not a function...
Can anyone please Guide me where i am wrong ?
i have gone through
How do I show nested data into a tree?
but here my Zone1s can have Zone1s in themselves that's the difference.
You should add a root attribute to your Store :
var store =Ext.create('Ext.data.Store', {
model: 'Zone1s',
autoLoad: true,
root: {
text: 'Zone1s',
id: 'Zone1s',
expanded: true
}
});
If you do not want to see the root node, use the rootVisible attribute :
Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 200,
height: 150,
store: store,
rootVisible : false,
renderTo: Ext.getBody()
});

ExtJs 4 Reload Application

In my application all component's titles/texts are localized based on store loaded before Application launch. In application i have button that changes store url and reloads the store to switch language. The problem is that all the classess are already loaded so components are rendered with previous locale. Here is the code of the button:
tbar: [{
xtype: 'button',
id: 'btn-test',
text: 'xxx',
handler: function() {
lang = 'en';
i18n.getBundlestore().load({url:'/GSIP/resources/gsip/i18n/bundle-' + lang + '.properties'});
//bun = Ext.create('I18N.ResourceBundle');
Ext.getCmp('mainview').destroy();
Ext.create('Ext.container.Viewport', {
id: 'mainview',
layout: 'border',
items: [
{
xtype: 'gsip_mainpanel',
region: 'center',
items: [{
xtype: 'gsip_categoriestabpanel'
}]
}
]
The exact same viewport creation is in my Application.js. lang and i18n are global variables. Old viewport is destroyed and new is created but how to force to reload classess. I dont want to use window.location.
Code updated:
handler: function() {
lang = 'en';
Ext.getCmp('mainview').destroy();
i18n.getBundlestore().load({url:'/GSIP/resources/gsip/i18n/bundle-' + lang + '.properties',
callback: function() {
Ext.create('Ext.container.Viewport', {
id: 'mainview',
layout: 'border',
items: [
{
xtype: 'gsip_mainpanel',
region: 'center',
items: [{
xtype: 'gsip_categoriestabpanel'
}]
}
]
});
}
});
}
CategoriesTabPanel:
Ext.define('GSIP.view.CategoriesTabPanel' ,{
extend: 'Ext.tab.Panel',
alias : 'widget.gsip_categoriestabpanel',
layout: 'fit',
items: [{
xtype: 'gsip_planytabpanel',
title: i18n.getMsg('key-1')
},{
xtype: 'gsip_adresytabpanel',
title: i18n.getMsg('key-2')
}],
initComponent: function() {
this.callParent(arguments);
}
});
and ResourceBundle (i18n variable is an instance of this class):
Ext.define('I18N.ResourceModel',{
extend: 'Ext.data.Model',
fields: ['key', 'value']
});
Ext.define('I18N.ResourceStore',{
extend: 'GSIP.core.RegisteredStore',
model: 'I18N.ResourceModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/GSIP/resources/gsip/i18n/bundle-' + lang + '.properties',
reader: {
type: 'json',
root: 'pl',
successProperty: 'success'
}
}
});
Ext.define('I18N.ResourceBundle' ,{
config: {
bundlestore: Ext.create('I18N.ResourceStore'),
},
constructor: function(config) {
this.initConfig(config);
return this;
},
getMsg: function(key) {
return this.bundlestore.getAt(this.bundlestore.findExact('key', key)).get('value');
}
},function(){
//callback function, called before store load :(
}
);
Within the definition of widget.gsip_categoriestabpanel you set items as a config. This means it will always reference the same object (and not the updated one). As first step, you should move the items definition to initComponent, there you can also console.log(i18n) to see it's the right one.

Sencha Touch Slide

I am starting to use Sencha Touch and have already read their "Getting Started" gide, however I am currently stuck in what I want to do and haven't been able to find any proper tutorial or example of what I need.
I want to make a panel so that when a user clicks on a specific button the panel slides and the toolbar on top disappears (or slides as well) and a new one appear just as it would happen on a native iOS app.
Here's my Sencha code so far:
Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function() {
/*HANDLERS
*********************************************************************************/
var showAlert = function(btn, event) {
Ext.Msg.alert('Title', 'Diste ' + event.type + ' en el botón "' + btn.text + '"', Ext.emptyFn);
};
var tapHandler = function(button, event) {
};
/*BUTTONS
*********************************************************************************/
var aboutAppBtn = [{
text: 'Sobre App',
ui: 'round',
handler: showAlert
}];
var checkInBtn = [{
text: 'Check-in',
ui: 'forward',
handler: tapHandler
}];
var buscarCercaBtn = [{
text: 'Buscar local...',
ui: 'button',
handler: showAlert
}];
var buttonsGroup1 = [{
text: 'Sobre App',
ui: 'round',
handler: showAlert
}, {
text: 'Check-in',
ui: 'forward',
handler: tapHandler
}];
/*PHONE || SCREEN
**********************************************************************************/
if (Ext.is.Phone) {// Phone has far less screen real-estate
var dockedItems = [{
xtype: 'toolbar',
dock : 'top',
ui: 'light',
title: 'My Toolbar',
items: buttonsGroup1
}];
}else{
//var dockedItems = [topTB];
aboutAppBtn.push({xtype: 'spacer'});
var dockedItems = [{
xtype: 'toolbar',
dock : 'top',
ui: 'light',
title: 'My Toolbar',
items: aboutAppBtn.concat(checkInBtn)
},{
xtype: 'button',
dock: 'bottom',
ui: 'action',
text: 'Buscar local...',
handler: showAlert
}];
}
var green = {
style: 'background-color:#3b7E00; color:white;',
title: 'Green',
html: 'Green'
};
var blue = {
style: 'background-color:#0F0; color:white;',
title: 'Blue',
html: 'Blue'
};
/*PANELS
**********************************************************************************/
var mainPanel = new Ext.Panel({
dockedItems: dockedItems,
layout: 'card',
cardSwitchAnimation: {type: 'flip', duration: 500},
fullscreen : true,
items: [green, blue]
});
}
});
To make the card transition when you click a button use the setActiveItem method in your handler:
var tapHandler = function(button, event) {
mainPanel.setActiveItem(1);
};
It can also take a reference to the panel component directly (which is useful if you ever change the order of the cards and the indices change).
Your toolbar is docked to the outer container, not to the cards, so it won't change when you change cards. You could dock two different toolbars to the card panels instead if you wanted it to change (or alter it programmatically, I suppose).
Also you can use the 'spacer' type to spread your buttons apart to each side of the tool. Here is your code adjusted to do what I think you probably want (on phone only, for clarity)
Ext.setup({
onReady: function() {
/*HANDLERS
*********************************************************************************/
var showAlert = function(btn, event) {
Ext.Msg.alert('Title', 'Diste ' + event.type + ' en el botón "' + btn.text + '"', Ext.emptyFn);
};
var tapHandler = function(button, event) {
mainPanel.setActiveItem(blue, {type: 'slide'});
};
var backHandler = function(button, event) {
mainPanel.setActiveItem(green, {type: 'slide', direction: 'right'});
};
/*UI
*********************************************************************************/
var green = new Ext.Panel({
dockedItems: [{
xtype: 'toolbar',
ui: 'light',
title: 'My Toolbar',
items: [{
text: 'Sobre App',
ui: 'round',
handler: showAlert
}, { xtype:'spacer'}, {
text: 'Check-in',
ui: 'forward',
handler: tapHandler
}]
}],
style: 'background-color:#3b7E3b',
html: 'Green'
});
var blue = new Ext.Panel({
dockedItems: [{
xtype: 'toolbar',
ui: 'light',
title: 'Check-in',
items: [{
text: 'Back',
ui: 'back',
handler: backHandler
}]
}],
style: 'background-color:#3b3b7E',
html: 'Blue'
});
var mainPanel = new Ext.Panel({
layout: 'card',
fullscreen : true,
items: [green, blue]
});
}
});

Resources