Sencha Touch 2 Carousel: Lock Swiping of Start/End Page - sencha-touch

I want Carousel to stop swiping at start and end of the pages.
I mean to prevent the end page to swipe to the right and the start page to swipe to the left:
Is there any config or some other way to implement it?
Thank you in Advance.

By default, ST2's carousel component has this configuration. So, you need not put in any extra effort to achieve this.
Look at this example from Sencha's website. When you reach the last item, it will prevent swiping to the right and when you are on first item, it will prevent swiping to the left.
Ext.create('Ext.Carousel', {
fullscreen: true,
defaults: {
styleHtmlContent: true
},
items: [
{
html : 'Item 1',
style: 'background-color: #5E99CC'
},
{
html : 'Item 2',
style: 'background-color: #759E60'
},
{
html : 'Item 3'
}
]
});

You can create your own carousel and then override the onDrag event following is the code form Ext.carousel.Carousel
Ext.define('Ext.carousel.Custom', {
extend: 'Ext.carousel.Carousel',
onDrag: function(e) {
if (!this.isDragging) {
return;
}
var startOffset = this.dragStartOffset,
direction = this.getDirection(),
delta = direction === 'horizontal' ? e.deltaX : e.deltaY,
lastOffset = this.offset,
flickStartTime = this.flickStartTime,
dragDirection = this.dragDirection,
now = Ext.Date.now(),
currentActiveIndex = this.getActiveIndex(),
maxIndex = this.getMaxItemIndex(),
lastDragDirection = dragDirection,
offset;
if ((currentActiveIndex === 0 && delta > 0) || (currentActiveIndex === maxIndex && delta < 0)) {
delta *= 0.5;
}
offset = startOffset + delta;
if (offset > lastOffset) {
dragDirection = 1;
}
else if (offset < lastOffset) {
dragDirection = -1;
}
if (dragDirection !== lastDragDirection || (now - flickStartTime) > 300) {
this.flickStartOffset = lastOffset;
this.flickStartTime = now;
}
this.dragDirection = dragDirection;
// now that we have the dragDirection, we should use that to check if there
// is an item to drag to
if ((dragDirection == 1 && currentActiveIndex == 0) || (dragDirection == -1 && currentActiveIndex == maxIndex)) {
return;
}
this.setOffset(offset);
}
});
reference :=Link

Related

Row Span AutoGrouping and Bug

I've created a plnkr to auto-group row-spans the way you would really expect it to work out of the box IMHO.
Anyhow... doing this surfaces an apparent bug... the rowSpan is not consistently applied to the grid.. if you scroll up and down, it sometimes applies, and sometimes does not.
In the screenshot below... you can see 'Aaron Peirsol' is spanning... but if I scroll up and down it might not span on him... not consistent.
Here 'Aaron Peirsol' is no longer spanning all 3 rows -- all I did was scroll up and back down
See this Sample
https://plnkr.co/edit/UxOcCL1SEY4tScn2?open=app%2Fapp.component.ts
Here I've added columndefs for the grouping
{
field: 'athlete',
rowSpan: params => params.data.groupCount,
cellClassRules: {
'cell-span': "data.isFirst && data.groupCount>1",
},
width: 200,
},
{field:'groupCount', width: 20}, /* included for debugging */
{field:'isFirst', width: 20}, /* included for debugging */
And here I'm doing the auto-grouping code:
onGridReady(params: GridReadyEvent) {
this.http
.get<any[]>('https://www.ag-grid.com/example-assets/olympic-winners.json')
.subscribe((data) => {
let groupKey = 'athlete';
let sorted = data.sort((a,b) => (a[groupKey] > b[groupKey]) ? 1 :
((b[groupKey] > a[groupKey]) ? -1 : 0));
let filtered = sorted.filter(x => {
return x[groupKey] < 'Albert' && x[groupKey];
});
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
let keyValue = x[key];
if (rv[keyValue] === undefined)
{
rv[keyValue] = 0;
}
if (keyValue) {
rv[keyValue] ++;
}
return rv;
}, {});
};
let grouped = groupBy(filtered, groupKey);
let prev = '';
for (let i=0; i<filtered.length; i++)
{
let keyValue = filtered[i][groupKey];
filtered[i]['groupCount'] = grouped[keyValue];
if (keyValue == prev)
{
filtered[i]['isFirst'] = false;
}
else
{
filtered[i]['isFirst'] = true;
}
prev = keyValue;
}
this.rowData = filtered});
}
OK, found the issue...
rowSpan function must only return a span count for the first row of the span...
every other row it must return 1
I've updated the plunker
public columnDefs: ColDef[] = [
{
field: 'athlete',
rowSpan: params => params.data.groupRowCount == 1 ? params.data.groupCount: 1, //THIS IS CRUCIAL.. only return count for first row
cellClassRules: {
'cell-span': "data.groupRowCount==1 && data.groupCount>1",
},
width: 200,
},

Dataview Component change event executes in infinite loop

I am trying to create a dataview component with a panel and a toggle button. The inital states of the toggle button is set by a field in the store and on clicking the toggle button, certain functions needs to be called to update the state in backend.But since I am initializing the states of toggle button from backend when page loads, the change event is called on start itself, due to which the button toggles infinitely by calling the logic inside the CHANGE EVENT part back to back.
Kindly help as on how to prevent the change event from being called on page load and to be only called when user clicks on the toggle button?
/**
var togglevalue = 0, count = 0;
Ext.define('PMDQ.view.EquipmentDVItem', {
extend: 'Ext.dataview.component.DataItem',
requires: [
'Ext.field.Toggle'
],
alias: 'widget.equipmentdvitem',
config: {
layout: 'fit',
cls: 'cartitem-cls',
dataMap: {
// Map product's data to dataItem setter
getEqpmntdvinneritem: {
setDisplayName: 'ChecklistText'
},
getTogglebutton: {
setValue: "ItemValue"
}
},
eqpmntdvinneritem: {
flex: 2
},
togglebutton: {
itemId: "itemspinnerfield",
flex: 1,
name: 'single_toggle'
},
layout: {
type: 'hbox',
align: 'center'
}
},
applyEqpmntdvinneritem: function (config) {
console.log(PMDQ.view.EquipmentDVInnerItem);
return Ext.factory(config,
PMDQ.view.EquipmentDVInnerItem,
this.getEqpmntdvinneritem());
},
updateEqpmntdvinneritem: function (newItemLine, oldItemLine) {
if (oldItemLine) {
this.remove(oldItemLine);
}
if (newItemLine) {
// Attach lines to DataView
newItemLine.on('tap', this.onTogglebuttonTap, this);
this.add(newItemLine);
}
},
applyTogglebutton: function (config) {
return Ext.factory(config, Ext.field.Toggle, this.getTogglebutton());
},
updateTogglebutton: function (newTogglebutton, oldTogglebutton) {
if (oldTogglebutton) {
this.remove(oldTogglebutton);
}
if (newTogglebutton) {
// add an event listeners for the `tap` event onto the new button, and tell it to call the onNameButtonTap method
// when it happens
newTogglebutton.on('load', this.onTogglebuttonTap, this);
newTogglebutton.on('change', this.onTogglebuttonChange, this);
this.add(newTogglebutton);
}
},
onTogglebuttonTap: function () {
var record = this.getRecord(), me = this;
count = 0;
},
onTogglebuttonChange: function (slider, newValue, oldValue, thumb) {
var record = this.getRecord(), me = this , store = me.getStore();
if (oldValue == 0 && newValue == 1) {
var val = record.get("InputAllowed");
if (val == "X") {
alert("onMPValueEnteronMPValueEnter" + count);
me.fireEvent("onMPValueEnter", this, record);
togglevalue = 0;
}
else {
me.fireEvent("onToggleSave", this, oldValue, newValue, record);
togglevalue = 0;
}
}
else if (oldValue == 1 && newValue == 0) {
alert("onToggleSave Off" + count);
me.fireEvent("onToggleSave", this, oldValue, newValue, record);
togglevalue = 0;
}
}
});
You can add a conditional in the listener which will then be set the first time that the item is "set" and thereafter you can act as you normally wanted.
So for example in the config of the toggle you could add a property to check and change on instantiation.
togglebutton: {
toggleSet: false, // <-- for example here.
itemId: "itemspinnerfield",
flex: 1,
name: 'single_toggle'
}
Then amend your listener to check if it's only been loaded and set the first or subsequent times:
onTogglebuttonChange: function (slider, newValue, oldValue, thumb) {
// Added a conditional to check if the toggle has been initially set or not.
if (!slider.toggleSet){
// Now set the toggleSet so next time the listener runs, it will continue below.
slider.toggleSet = true;
return;
}
var record = this.getRecord(), me = this , store = me.getStore();
if (oldValue == 0 && newValue == 1) {
var val = record.get("InputAllowed");
if (val == "X") {
alert("onMPValueEnteronMPValueEnter" + count);
me.fireEvent("onMPValueEnter", this, record);
togglevalue = 0;
}
else {
me.fireEvent("onToggleSave", this, oldValue, newValue, record);
togglevalue = 0;
}
}
else if (oldValue == 1 && newValue == 0) {
alert("onToggleSave Off" + count);
me.fireEvent("onToggleSave", this, oldValue, newValue, record);
togglevalue = 0;
}
}

ST2.1 vs ST2.2 chart sprite style renderer

With ST2.1, I had a scatter graph with a renderer function changing all sprite rotation and color based on values in the store. It was working well.
I upgraded to ST2.2.0 and now I'm having trouble rebuilding the same function.
code for ST2.1 - was working.
series: [
{
type: 'scatter',
xField: 'local_date_time',
yField: 'wind_spd_kt',
marker: { ...
},
style: {
renderer: function (target, sprite, index, storeItem) {
var sweather = Ext.getStore('Sun');
if (index < sweather.getCount() ){
target.rotationRads = storeItem.data.sun_dir;
if (storeItem.data.sun_spd_kt < 10) {
target.fill = '#ff0000'; //red
//console.log ( index + ' : <10 :' + storeItem.data.sun_spd_kt )
}
else { target.fill = '#00EE00'; } //green
}
}
},
COde in ST2.2.0 that I tried:
style: {
renderer: function (sprite, config, rendererData, index) {
sprite.rotationRads = rendererData.store.data.all[index].raw.sun_dir
sprite.attr.fillStyle = '#ff0000'
}
}
Has Anyone used "renderer" successfully in ST2.2.0?
I made up a solution to your problem. Could you try the following ?
renderer: function (sprite, config, rendererData, index) {
if (index % 2 == 0) {
return { strokeStyle: 'red' };
}
}

Disable carousel overscroll/overdrag in Sencha Touch

At the end or beginning of a Sencha Touch 2 carousel, a user can drag the item past where it should be able to go and display the white background (screenshot here: http://i.imgur.com/MkX0sam.png). I'm trying to disable this functionality, so a user can't drag past the end/beginning of a carousel.
I've attempted to do this with the various scrollable configurations, including the setup that is typically suggested for dealing with overscrolling
scrollable : {
direction: 'horizontal',
directionLock: true,
momentumEasing: {
momentum: {
acceleration: 30,
friction: 0.5
},
bounce: {
acceleration: 0.0001,
springTension: 0.9999,
},
minVelocity: 5
},
outOfBoundRestrictFactor: 0
}
The above configuration, especially outOfBoundRestrictFactor does stop the ability to drag past the end, but it also stops the ability to drag anywhere else in a carousel either...so that doesn't work. I've screwed around with all of the other configurations to no positive effect.
Unfortunately, I haven't been able to find much on modifying the configurations of dragging. Any help here would be awesomesauce.
What you need to do is override the onDrag functionality in Carousel. This is where the logic is to detect which direction the user is dragging, and where you can check if it is the first or last item.
Here is a class that does exactly what you want. The code you are interested in is right at the bottom of the function. The rest is simply taken from Ext.carousel.Carousel.
Ext.define('Ext.carousel.Custom', {
extend: 'Ext.carousel.Carousel',
onDrag: function(e) {
if (!this.isDragging) {
return;
}
var startOffset = this.dragStartOffset,
direction = this.getDirection(),
delta = direction === 'horizontal' ? e.deltaX : e.deltaY,
lastOffset = this.offset,
flickStartTime = this.flickStartTime,
dragDirection = this.dragDirection,
now = Ext.Date.now(),
currentActiveIndex = this.getActiveIndex(),
maxIndex = this.getMaxItemIndex(),
lastDragDirection = dragDirection,
offset;
if ((currentActiveIndex === 0 && delta > 0) || (currentActiveIndex === maxIndex && delta < 0)) {
delta *= 0.5;
}
offset = startOffset + delta;
if (offset > lastOffset) {
dragDirection = 1;
}
else if (offset < lastOffset) {
dragDirection = -1;
}
if (dragDirection !== lastDragDirection || (now - flickStartTime) > 300) {
this.flickStartOffset = lastOffset;
this.flickStartTime = now;
}
this.dragDirection = dragDirection;
// now that we have the dragDirection, we should use that to check if there
// is an item to drag to
if ((dragDirection == 1 && currentActiveIndex == 0) || (dragDirection == -1 && currentActiveIndex == maxIndex)) {
return;
}
this.setOffset(offset);
}
});

How to swap CSS in Sencha Touch

I need to swap the css for my Mobile application done in Sencha Touch.
At the moment I=m not obtaining any result.
Could you tell me how to do it?
Thanks
I solved the issue using this code...
var accessibilityButton = {
xtype: 'button',
ui: 'custom-btn-confirm',
maxWidth: '360px',
centered: true,
flex: 1,
scope: this,
style: 'color: #ffffff',
text: 'Active Accesibility',
ui: 'custom-btn-confirm',
handler: function changeStyle() {
// Swap the CSS for Accessibility
var i, a, url, btn;
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
if(a.getAttribute("rel").indexOf("style") != -1) {
url = a.href;
btn = document.getElementById("ext-element-114");
if(url.lastIndexOf('app.css') !== -1) {
a.href = 'resources/css/app-accesibility.css';
btn.textContent = "AAAA";
}
else {
a.href = 'resources/css/app.css';
btn.textContent = "BBBB";
}
}
}
}
};