watusi / jquery-mobile-iscrollview

JQuery Mobile widget plug-in for easy use of the iScroll javascript scroller.
408 stars 183 forks source link

More Strange Behavior on iOS pinch/zoom with scale below 1 #32

Closed brandonhall closed 7 years ago

brandonhall commented 12 years ago

Hey Jon,

Thanks for the tip about double refresh and refreshdelay. That seemed to fix the Opera issue without the need for another method call. At this point, we're trying to get a full zoom out working. Basically, we get the scale needed for the entire item to fit onto the screen and set that as zoomMin.

In the interest of sharing, here's the code for that implementation in Backbone with jQM:

this._zoomMin = window.innerWidth /
    (this._record.width + this._horizontalAdjustment);

// Bunch of other options

$.mobile.iscrollview.prototype.options.zoomMin = this._zoomMin;

this._scroller = this.$el.find(':jqmData(iscroll)').iscrollview();
$('.iscroll-wrapper', this.$el)
    .on('iscroll_onzoomend', _.bind(this._handleZoomEnd, this));

_handleZoomEnd: function(event, data) {
    var scale = data.iscrollview.iscroll.scale;
    var newHeight = (this._record.height * scale)
        + this._scrollerHeightPadding;

    if (newHeight <= this._scrollerHeight) {
        this.$el.find('.itemWrapper').css('height', newHeight);
        this._scroller.jqmData('iscrollview').refresh();
    } else {
        this.$el.find('.itemWrapper').css('height', this._scrollerHeight);
        this._scroller.jqmData('iscrollview').refresh();
    }
},

A few notes about that code. The horizontal adjustment accounts for the widths of other controls. It's an arbitrary number. The refresh calls are to ensure the height of our container adjusts properly.

Dead simple and it works beautifully out of the box on Android, Opera and Firefox. However, on iOS, I had to modify the actual iscroll.js because the control wouldn't update in time. On line 525 of iscroll.js...

// BEGIN TEMP MOD
// Having a delay on iOS when scale is less than 1
// doesn't reset the control properly. I still need
// to determine if it's a control problem or something
// to do with our implementation

var iosDuration = (isIDevice && scale < 1) ? '0ms' : '200ms';
that.scroller.style[transitionDuration] = iosDuration;

// ORIGINAL VALUE: that.scroller.style[transitionDuration] = '200ms';
// END MOD

Naturally, setting the refreshDelay option doesn't affect this call in iscroll.js because it is hard-coded. Any ideas on fixing this within either jquery.mobile.iscrollview or our implementation? Or, do I need to take this up with the folks at iscroll?

As always, thanks for your help.

Brandon

brandonhall commented 12 years ago

Hi Jon,

Following up here to see if you had any ideas.

jtara commented 12 years ago

I was thinking you might be able to change that in a callback, but onBeforeScrollEnd is before iScroll sets it, and onZoomEnd is after.

You might want to point this out to Mateo, since he is working on iScroll5. It would make sense to make this an option.