BootStrap Transition to next tab from Carousel with manos.malihu plugin - android

Please help me in finding a solution that will be very useful for many other people after me.
I have a simple/standard carousel made in Bootstrapie. The problem starts when I want with the swipe right or left go to next or previous tab in the carousel at the browser in Android.
I know that is the mass of plug-ins that provide such functionality Bootstrapping carousel. I used the simplest way using component "touch" from jQuery Mobile. When I use desktop browser (chrome, ff, opera) and using the mouse to swipe left/right it all works nicely (changing cards).
However, when I use the android browser I haven't such a possibility. My diagnosed why this happens (unfortunately, this is so independent of plugin enabled swipe and I lost a lot of time trying to find a running plugin - tested hammer.js bootstrap-touch-carousel.js, slick.js, jquery.touchSwipe.js, etc.). The reason is use by me a configurable scrollbar'a from plugin - manos.malihu. My diagnosis is to find part of code in the above plugin: jquery.Custom Scrollbar.js whose responsible for swipe (and blocking swipe from e.g. jQuery Mobile). Below I paste code responsible for the swipe in manos.malihu plugin:
/*
TOUCH SWIPE EVENTS
scrolls content via touch swipe
Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices
*/
_contentDraggable=function(){
var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
namespace=pluginPfx+"_"+d.idx,
mCustomScrollBox=$("#mCSB_"+d.idx),
mCSB_container=$("#mCSB_"+d.idx+"_container"),
mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount,
durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag,
iframe=mCSB_container.find("iframe"),
events=[
"touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start
"touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move
"touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end
],
touchAction=document.body.style.touchAction!==undefined;
mCSB_container.bind(events[0],function(e){
_onTouchstart(e);
}).bind(events[1],function(e){
_onTouchmove(e);
});
mCustomScrollBox.bind(events[0],function(e){
_onTouchstart2(e);
}).bind(events[2],function(e){
_onTouchend(e);
});
if(iframe.length){
iframe.each(function(){
$(this).load(function(){
/* bind events on accessible iframes */
if(_canAccessIFrame(this)){
$(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){
_onTouchstart(e);
_onTouchstart2(e);
}).bind(events[1],function(e){
_onTouchmove(e);
}).bind(events[2],function(e){
_onTouchend(e);
});
}
});
});
}
function _onTouchstart(e){
if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;}
touchable=1; touchDrag=0; docDrag=0; draggable=1;
$this.removeClass("mCS_touch_action");
var offset=mCSB_container.offset();
dragY=_coordinates(e)[0]-offset.top;
dragX=_coordinates(e)[1]-offset.left;
touchIntent=[_coordinates(e)[0],_coordinates(e)[1]];
}
function _onTouchmove(e){
if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;}
if(!o.documentTouchScroll){e.preventDefault();}
e.stopImmediatePropagation();
if(docDrag && !touchDrag){return;}
if(draggable){
runningTime=_getTime();
var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left,
easing="mcsLinearOut";
touchMoveY.push(y);
touchMoveX.push(x);
touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]);
if(d.overflowed[0]){
var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(),
prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*2<touchIntent[2] || o.axis==="yx"));
}
if(d.overflowed[1]){
var limitX=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(),
preventX=((dragX-x)>0 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*2<touchIntent[3] || o.axis==="yx"));
}
if(prevent || preventX){ /* prevent native document scrolling */
if(!touchAction){e.preventDefault();}
touchDrag=1;
}else{
docDrag=1;
$this.addClass("mCS_touch_action");
}
if(touchAction){e.preventDefault();}
amount=o.axis==="yx" ? [(dragY-y),(dragX-x)] : o.axis==="x" ? [null,(dragX-x)] : [(dragY-y),null];
mCSB_container[0].idleTimer=250;
if(d.overflowed[0]){_drag(amount[0],durA,easing,"y","all",true);}
if(d.overflowed[1]){_drag(amount[1],durA,easing,"x",overwrite,true);}
}
}
function _onTouchstart2(e){
if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;}
touchable=1;
e.stopImmediatePropagation();
_stop($this);
startTime=_getTime();
var offset=mCustomScrollBox.offset();
touchStartY=_coordinates(e)[0]-offset.top;
touchStartX=_coordinates(e)[1]-offset.left;
touchMoveY=[]; touchMoveX=[];
}
function _onTouchend(e){
if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;}
draggable=0;
e.stopImmediatePropagation();
touchDrag=0; docDrag=0;
endTime=_getTime();
var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
if((endTime-runningTime)>30){return;}
speed=1000/(endTime-startTime);
var easing="mcsEaseOut",slow=speed<2.5,
diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0];
distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX];
var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])];
speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed];
var a=[
Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])),
Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1]))
];
amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null];
durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia];
var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */
amount[0]=absDistance[0]>md ? amount[0] : 0;
amount[1]=absDistance[1]>md ? amount[1] : 0;
if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);}
if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);}
}
function _m(ds,s){
var r=[s*1.5,s*2,s/1.5,s/2];
if(ds>90){
return s>4 ? r[0] : r[3];
}else if(ds>60){
return s>3 ? r[3] : r[2];
}else if(ds>30){
return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2];
}else{
return s>8 ? s : r[3];
}
}
function _drag(amount,dur,easing,dir,overwrite,drag){
if(!amount){return;}
_scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag});
}
},
I see that in desktop browser is used to swipe from jQuery mobile. Changing cards from carousel works with swipe by mouse (press left mouse button and drag to left or right).
Code with swipe using jQuery mobile:
$('.carousel').swiperight(function() {
$(this).carousel('prev');
});
$('.carousel').swipeleft(function() {
$(this).carousel('next');
});
After many attempts I cann't make changes in "jquery.mCustomScrollbar.js" such to get the same functionality in android browser with touch of a finger. My a function call from "jquery.mCustomScrollbar.js":
jQuery('.carousel-item').mCustomScrollbar({ axis:"y", theme: "rounded-dots", scrollButtons: { enable: true }, scrollInertia: 100});
For you it will be easier than for me to add/change code snippet in jquery.mCustomScrollbar.js to get similar functionality for both browsers (desktop, android).
P.S.
I warn you, when I use:
contentTouchScroll: false
In fact, I have similar functionality on both browsers, but this not the way because I block possibility to scroll up/down with touch(swipe) your finger up/down.
Issue reported on github creator plugin
[but I guess that support from creators rather isn't possible at this moment]
I would be very grateful for your help. I lost too much time trying to solve the problem yourself
Regards Zic

This should only remove e.stopImmediatePropagation() from above part of plugin (_OnTouch/Start/Move/End)

Related

How to have separate pages for iOS Web App and just browser? [duplicate]

If a user visits my websites example, from Safari Mobile how could I place there a blank page that says "Add To Homescreen."? Once added it would show different content.
You'll want to check two things. First, is it running on an iOS device? Second, is window.navigator.standalone == true?
window.navigator.standalone is primarily used by Webkit browsers to indicate the app is in fullscreen (or standalone) mode. Plenty of devices (like phones running Android), support this property, but don't have the option to 'Add to Homescreen' like iOS devices do, so you need to check both.
Demo:
Javascript:
function isIOS() {
var userAgent = window.navigator.userAgent.toLowerCase();
return /iphone|ipad|ipod/.test( userAgent );
};
function isStandalone() {
return ( isIOS() && window.navigator.standalone );
};
window.onload = function () {
if( isStandalone() || !isIOS() ) { //either ios+standalone or not ios
//start app
} else {
//display add to homescreen page
};
};
Check window.navigator.standalone.
Slight slight different code, based on #ThinkingStiff solution, and this other question on this Post, to support IOS7 detection to provide CSS interface to add more padding-top in case of transparent app title.
isIOS7 = function() {
return navigator.userAgent.match(/(iPad|iPhone|iPod touch);.*CPU.*OS 7_\d/i);
};
isStandaloneAndIOS7 = function() {
return isIOS7() && window.navigator.standalone;
};
if (isStandaloneAndIOS7()) {
body = document.getElementsByTagName("body")[0];
body.className = body.className + " standalone";
}

Ionic - disable animation for nav bar

My app has a static header. Meaning it remains the same in all views.
The problem is that when I use the <ion-nav-bar> directive the header is animated every time the view changes.
On IOS it's not that bad because the entire is sliding in, but on Android it looks like it flickers.
How can I disable the animation entirely?
I already tried using $ionicConfigProvider.navBar.transition('none'); in the app.config section, but it actually made it worse (also flickers on IOS).
I created a simple codepen (the default transition appears to that of IOS, but if you open the developer console on chrome and change to an android device you can see the flickering).
if you really no idea to how solve this.
you can modify the transition function
First, in app.config section
$ionicConfigProvider.navBar.transition('android');
then, modify ionic transition function
$ionicConfigProvider.transitions.navBar.android = function(enteringHeaderBar, leavingHeaderBar, direction, shouldAnimate) {
function setStyles(ctrl, opacity) {
if (!ctrl) return;
var css = {};
// ionic original
// css.opacity = opacity === 1 ? '' : opacity;
// modify
if (opacity === 1) {
css.opacity = '';
css.display = '';
} else {
css.opacity = opacity;
css.display = 'none'; // let leavingHeaderBar immediately disappear
}
ctrl.setCss('buttons-left', css);
ctrl.setCss('buttons-right', css);
ctrl.setCss('back-button', css);
ctrl.setCss('back-text', css);
ctrl.setCss('title', css);
}
return {
run: function(step) {
setStyles(enteringHeaderBar.controller(), step);
setStyles(leavingHeaderBar && leavingHeaderBar.controller(), 1 - step);
},
shouldAnimate: shouldAnimate && (direction == 'forward' || direction == 'back')
};
};
If you are using Ionic 2 or higher, use the following CSS only:
.toolbar{
.title, button{
opacity: 1!important;
transform: none!important;
}
}

iscroll is not working properly for dynamic form in phonegap

I have developed android phonegap app.I have a appended the dynamic form contains 'input' and 'select' in the div.I need to get scrollbar for that div.So i used iScroll.js but its not working properly.While typing in the textbox suddenly scrollbar disappears.This problem occurring often.
Here is my code:
function loaded()
{
var myScroll = new iScroll('wrapper',
{
scrollbarClass: 'myScrollbar',
useTransform: false,
vScroll: true,
onBeforeScrollStart: function (e)
{
var target = e.target;
while (target.nodeType != 1) target = target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA')
e.preventDefault();
}
});
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', loaded, false);
Please kindly guide me.Thanks in Advance
so a couple of things that will be helpful -
define your myScroll variable outside of your loaded function that way you can access it anywhere.
also after your content has loaded call myScroll.refresh() and have at least a 1ms delay on it. little hack that goes a long way.

Is it possible to scroll divs in Chrome for Android?

Here is a chunk of text inside a scrollable div.
I can scroll it with two fingers in Chrome for Mac. I can scroll it with one finger on my iPad. However, I can't find any way to scroll it in Chrome for Android.
Perhaps there's a work-around using the touch API?
Another quick fix for Chrome for Android (http://chris-barr.com/index.php/entry/scrolling_a_overflowauto_element_on_a_touch_screen_device/)
First create a function to check whether the it is a touch device...
function isTouchDevice(){
try {
document.createEvent("TouchEvent");
return true;
} catch(e) {
return false;
}
}
then function to make div scrollable
function touchScroll(id){
if( isTouchDevice() ){ //if touch events exist...
var el = document.getElementById(id);
var scrollStartPos = 0;
document.getElementById(id).addEventListener("touchstart", function(event){
scrollStartPos = this.scrollTop + event.touches[0].pageY;
event.preventDefault();
}, false);
document.getElementById(id).addEventListener("touchmove", function(event){
this.scrollTop = scrollStartPos - event.touches[0].pageY;
event.preventDefault();
},false);
}
}
... call the function passing the element id
touchScroll("divIdName");
While browsing through the bug reports on this issue, I found this JavaScript library that solves the problem using touch events. Also it is reportedly fixed in Honeycomb, so hopefully the fix will hit people as soon as they push builds of Ice Cream Sandwich.
All android versions before 3.0 are bugged with overflow:scroll or auto (bug info).
For thoses using jQuery here is a quick fix :
function touchScroll(selector){
var scrollStartPos = 0;
$(selector).live('touchstart', function(event) {
scrollStartPos = this.scrollTop + event.originalEvent.touches[0].pageY;
});
$(selector).live('touchmove', function(event) {
this.scrollTop = scrollStartPos - event.originalEvent.touches[0].pageY;
});
}
and then if using modernizr :
if (Modernizr.touch) {
touchScroll($('.myScrollableContent'))
}
but it's not ideal because all touch-able devices will have this.
If you use Phonegap you can do (somewhere after phonegap inited):
if (window.device && device.platform=="Android" && parseInt(device.version) < 3){
touchScroll($('.myScrollableContent'))
}

Using iScroll prevents the keyboard from showing on my device

I am using iScroll for providing iPhone style scrolling. But, when clicking on the textboxes, the keyboard does not show up.
While trying to find the possible cause, I found that removing the iScroll script, makes it work normal, but in that case I miss the scrolling functionality.
Is this a bug in iScroll. If yes, is there a tested work-around? Or is there any alternative for iScroll?
Thanks in advance.
At least in iScroll 4, you can add this code to enable clicking of input fields. See the demo on Form-fields in the examples folder.
<script type="text/javascript">
var myScroll;
function loaded() {
myScroll = new iScroll('wrapper', {
useTransform: false,
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1) target = target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA')
e.preventDefault();
}
});
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', loaded, false);
</script>
I was able to solve the error. The problem was with the CSS.
I thought may be the CSS is somehow creating the problem. I concluded this on the basis that when I commented the CSS for wrapper and scroller, the keyboard showed up... but keeping them, the keyboard didn't work. I was using bottom: 0px;, which seemed to be somehow preventing the keyboard from showing.
Removing bottom: 0px; solved my problem.
Hope this helps others.
I added the following code to _start in iScroll 4.2 to solve this problem:
if (e && e.target && e.target.tagName) {
var bFocusField = ('|INPUT|TEXTAREA|BUTTON|SELECT|'
.indexOf('|' + e.target.tagName + '|') >= 0);
if (bFocusField || that.focusField) {
if (bFocusField) {
that.focusField = e.target;
} else {
that.focusField.blur();
that.focusField = null;
}
e.defaultPrevented = false;
e.returnValue = true;
return true;
}
}
Code is inserted below the initialization part of the function (that.moved = false; ... that.dirY = 0;).
Tested it on iPad 1 (iOS 5.1) and iPad 3 (iOS 6). The onscreen keyboard does not seem to interfere with iScroll (I do an iScroll.refresh() every 5 seconds).
I believe this solution is optimal
Tweak the code in iscroll.js, ( as follows )
onBeforeScrollStart: function (e) {
//e.preventDefault();
if (e.target.nodeName.toLowerCase() == "select" || e.target.tagName.toLowerCase() == 'input' || e.target.tagName.toLowerCase() == 'textarea'){
return;
}
},

Categories

Resources