Export 0.2.3
[platform/framework/web/web-ui-fw.git] / src / widgets / common / js / jquery.mobile.tizen.scrollview.js
index 2a023e7..fc39fbf 100644 (file)
@@ -60,6 +60,7 @@
                        showScrollBars:    true,
                        overshootEnable:   false,
                        outerScrollEnable: true,
+                       overflowEnable:    true,
                        scrollJump:        false,
                },
 
                                self = this;
 
                        this._$clip = $( this.element ).addClass("ui-scrollview-clip");
-                       this._$view = this._$clip.wrapInner("<div></div>").children()
+
+                       if ( this._$clip.children(".ui-scrollview-view").length ) {
+                               this._$view = this._$clip.children(".ui-scrollview-view");
+                       } else {
+                               this._$view = this._$clip.wrapInner("<div></div>").children()
                                                        .addClass("ui-scrollview-view");
+                       }
 
                        if ( this.options.scrollMethod === "translate" ) {
                                if ( this._$view.css("transform") === undefined ) {
 
                        this._view_offset = this._$view.offset().top - this._$clip.offset().top;
                        this._view_height = this._getViewHeight();
-                       this._clip_height = this._$clip.height();
 
                        this._sx = 0;
                        this._sy = 0;
                        this._add_event();
                        this._add_scrollbar();
                        this._add_scroll_jump();
+                       this._add_overflow_indicator();
                },
 
                _startMScroll: function ( speedX, speedY ) {
 
                        this._stopMScroll();
                        this._showScrollBars();
+                       this._showOverflowIndicator();
 
                        this._$clip.trigger( this.options.startEventName );
 
                                c = this._$clip.width();
                                v = this._$view.width();
 
+                               if ( (( this._sx === 0 && speedX > 0 ) ||
+                                       ( this._sx === -(v - c) && speedX < 0 )) &&
+                                               v > c ) {
+                                       return;
+                               }
+
                                ht.start( this._sx, speedX,
                                        duration, (v > c) ? -(v - c) : 0, 0 );
                                keepGoing = !ht.done();
                        }
 
                        if ( vt ) {
-                               c = this._clip_height;
-                               v = this._view_height;
+                               c = this._$clip.height();
+                               v = this._getViewHeight();
+
+                               if ( (( this._sy === 0 && speedY > 0 ) ||
+                                       ( this._sy === -(v - c) && speedY < 0 )) &&
+                                               v > c ) {
+                                       return;
+                               }
 
                                vt.start( this._sy, speedY,
                                        duration, (v > c) ? -(v - c) : 0, 0 );
                        }
 
                        this._hideScrollBars();
+                       this._hideOverflowIndicator();
                },
 
                _handleMomentumScroll: function () {
                                x = 0,
                                y = 0,
                                scroll_height = 0,
+                               self = this,
+                               end_effect = function ( dir ) {
+                                       setTimeout( function () {
+                                               self._effect_dir = dir;
+                                               self._setEndEffect( "in" );
+                                       }, 100 );
+
+                                       setTimeout( function () {
+                                               self._setEndEffect( "out" );
+                                       }, 350 );
+                               },
                                vt = this._vTracker,
                                ht = this._hTracker;
 
                                keepGoing = !vt.done();
 
                                if ( vt.getRemained() > this.options.overshootDuration ) {
-                                       scroll_height = this._view_height - this._clip_height;
-
-                                       if ( vt.isMin() ) {
+                                       scroll_height = this._getViewHeight() - this._$clip.height();
+
+                                       if ( !vt.isAvail() ) {
+                                               if ( this._speedY > 0 ) {
+                                                       this._outerScroll( vt.getRemained() / 3, scroll_height );
+                                               } else {
+                                                       this._outerScroll( y - vt.getRemained() / 3, scroll_height );
+                                               }
+                                       } else if ( vt.isMin() ) {
                                                this._outerScroll( y - vt.getRemained() / 3, scroll_height );
+
+                                               if ( scroll_height > 0 ) {
+                                                       end_effect( 1 );
+                                               }
                                        } else if ( vt.isMax() ) {
                                                this._outerScroll( vt.getRemained() / 3, scroll_height );
+
+                                               if ( scroll_height > 0 ) {
+                                                       end_effect( 0 );
+                                               }
                                        }
                                }
                        }
                        var translate,
                                transition;
 
+                       if ( this._endEffect ) {
+                               return;
+                       }
+
                        if ( !duration || duration === undefined ) {
                                transition = "none";
                        } else {
                        });
                },
 
+               _setEndEffect: function ( dir ) {
+                       var scroll_height = this._getViewHeight() - this._$clip.height();
+
+                       if ( this._softkeyboard ) {
+                               if ( this._effect_dir ) {
+                                       this._outerScroll( -scroll_height - this._softkeyboardHeight,
+                                                       scroll_height );
+                               } else {
+                                       this._outerScroll( this._softkeyboardHeight, scroll_height );
+                               }
+                               return;
+                       }
+
+                       if ( dir === "in" ) {
+                               if ( this._endEffect ) {
+                                       return;
+                               }
+
+                               this._endEffect = true;
+                               this._setOverflowIndicator( this._effect_dir );
+                       } else if ( dir === "out" ) {
+                               if ( !this._endEffect ) {
+                                       return;
+                               }
+
+                               this._endEffect = false;
+                               this._setOverflowIndicator( this._effect_dir );
+                       }
+               },
+
                _setCalibration: function ( x, y ) {
                        if ( this.options.overshootEnable ) {
                                this._sx = x;
                        }
 
                        if ( dirLock !== "x" && this._vTracker ) {
-                               scroll_height = this._view_height - this._clip_height;
+                               scroll_height = this._getViewHeight() - $c.height();
 
                                if ( y > 0 ) {
                                        this._sy = 0;
+
+                                       if ( this._didDrag && scroll_height > 0 ) {
+                                               this._effect_dir = 0;
+                                               this._setEndEffect( "in" );
+                                       }
                                } else if ( y < -scroll_height ) {
                                        this._sy = -scroll_height;
+
+                                       if ( this._didDrag && scroll_height > 0 ) {
+                                               this._effect_dir = 1;
+                                               this._setEndEffect( "in" );
+                                       }
                                } else {
+                                       if ( this._endEffect && this._sy !== y ) {
+                                               this._endEffect = false;
+                                               this._setOverflowIndicator();
+                                       }
+
                                        this._sy = y;
                                }
 
 
                                if ( sm === "translate" ) {
                                        this._setElementTransform( $sbt, "0px",
-                                               -y / this._view_height * $sbt.parent().height() + "px",
+                                               -y / this._getViewHeight() * $sbt.parent().height() + "px",
                                                duration );
                                } else {
-                                       $sbt.css( "top", -y / this._view_height * 100 + "%" );
+                                       $sbt.css( "top", -y / this._getViewHeight() * 100 + "%" );
                                }
                        }
 
                                return;
                        }
 
-                       if ( scroll_height < 0 ) {
-                               return;
-                       }
-
                        if ( y > 0 ) {
-                               sy = -y;
+                               sy = ( window.screenTop ? window.screenTop : -y );
                        } else if ( y < -scroll_height ) {
                                sy = -y - scroll_height;
                        } else {
 
                        if ( this._is_inputbox ) {
                                target.one( "resize.scrollview", function () {
-                                       if ( ey > self._clip_height ) {
-                                               self.scrollTo( -ex, self._sy - ey + self._clip_height,
+                                       if ( ey > $c.height() ) {
+                                               self.scrollTo( -ex, self._sy - ey + $c.height(),
                                                        self.options.snapbackDuration );
                                        }
                                });
 
                _propagateDragMove: function ( sv, e, ex, ey, dir ) {
                        this._hideScrollBars();
+                       this._hideOverflowIndicator();
                        this._disableTracking();
                        sv._handleDragStart( e, ex, ey );
                        sv._directionLock = dir;
                                newY,
                                dirLock;
 
-                       if ( Math.abs( this._startY - ey ) < mt && !this._didDrag ) {
-                               return;
-                       }
-
                        this._lastMove = getCurrentTime();
 
                        if ( !this._directionLock ) {
                        }
 
                        if ( dirLock !== "x" && this._vTracker ) {
+                               if ( Math.abs( this._startY - ey ) < mt && dirLock !== "xy" ) {
+                                       return;
+                               }
+
                                y = this._sy;
                                this._speedY = dy;
                                newY = y + dy;
                        this._setScrollPosition( newX, newY );
 
                        this._showScrollBars();
+                       this._showOverflowIndicator();
                },
 
                _handleDragStop: function ( e ) {
                                y;
 
                        if ( sx || sy ) {
-                               this._startMScroll( sx, sy );
+                               if ( !this._setGestureScroll( sx, sy ) ) {
+                                       this._startMScroll( sx, sy );
+                               }
                        } else {
                                this._hideScrollBars();
+                               this._hideOverflowIndicator();
                        }
 
                        this._disableTracking();
 
+                       if ( this._endEffect ) {
+                               this._setEndEffect( "out" );
+                               this._hideScrollBars();
+                               this._hideOverflowIndicator();
+                       }
+
                        return !this._didDrag;
                },
 
+               _setGestureScroll: function ( sx, sy ) {
+                       var self = this,
+                               reset = function () {
+                                       clearTimeout( self._gesture_timer );
+                                       self._gesture_dir = 0;
+                                       self._gesture_count = 0;
+                                       self._gesture_timer = undefined;
+                               };
+
+                       if ( !sy ) {
+                               return false;
+                       }
+
+                       dir = sy > 0 ? 1 : -1;
+
+                       if ( !this._gesture_timer ) {
+                               this._gesture_count = 1;
+                               this._gesture_dir = dir;
+
+                               this._gesture_timer = setTimeout( function () {
+                                       reset();
+                               }, 1000 );
+
+                               return false;
+                       }
+
+                       if ( this._gesture_dir !== dir ) {
+                               reset();
+                               return false;
+                       }
+
+                       this._gesture_count++;
+
+                       if ( this._gesture_count === 3 ) {
+                               if ( dir > 0 ) {
+                                       this.scrollTo( 0, 0, this.options.overshootDuration );
+                               } else {
+                                       this.scrollTo( 0, -( this._getViewHeight() - this._$clip.height() ),
+                                                       this.options.overshootDuration );
+                               }
+                               reset();
+
+                               return true;
+                       }
+
+                       return false;
+               },
+
                _enableTracking: function () {
                        this._dragging = true;
                },
                        this._scrollbar_showed = false;
                },
 
+               _resetOverflowIndicator: function () {
+                       if ( !this.options.overflowEnable || !this._overflowAvail || this._softkeyboard ) {
+                               return;
+                       }
+
+                       this._overflow_top.css( "-webkit-animation", "" );
+                       this._overflow_bottom.css( "-webkit-animation", "" );
+               },
+
+               _setOverflowIndicator: function ( dir ) {
+                       if ( dir === 1 ) {
+                               this._opacity_top = "0.2";
+                               this._opacity_bottom = "0.8";
+                       } else if ( dir === 0 ) {
+                               this._opacity_top = "0.8";
+                               this._opacity_bottom = "0.2";
+                       } else {
+                               this._opacity_top = "0.5";
+                               this._opacity_bottom = "0.5";
+                       }
+               },
+
+               _getOverflowIndicator: function ( opacity ) {
+                       if ( opacity === "0.2" ) {
+                               return "-lite";
+                       } else if ( opacity === "0.8" ) {
+                               return "-dark";
+                       }
+                       return "";
+               },
+
+               _showOverflowIndicator: function () {
+                       if ( !this.options.overflowEnable || !this._overflowAvail || this._softkeyboard ) {
+                               return;
+                       }
+
+                       this._overflow_top.css( "opacity", this._opacity_top );
+                       this._overflow_bottom.css( "opacity", this._opacity_bottom );
+
+                       if ( this._overflow_showed === true ) {
+                               return;
+                       }
+
+                       this._overflow_top.css( "-webkit-animation", "ui-overflow-show" +
+                                       this._getOverflowIndicator( this._opacity_top ) + " 0.3s 1 ease" );
+                       this._overflow_bottom.css( "-webkit-animation", "ui-overflow-show" +
+                                       this._getOverflowIndicator( this._opacity_bottom ) + " 0.3s 1 ease" );
+
+                       this._overflow_showed = true;
+               },
+
+               _hideOverflowIndicator: function () {
+                       var opacity_top,
+                               opacity_bottom;
+
+                       if ( !this.options.overflowEnable || !this._overflowAvail || this._softkeyboard ) {
+                               return;
+                       }
+
+                       if ( this._overflow_showed === false ) {
+                               return;
+                       }
+
+                       opacity_top = this._overflow_top.css( "opacity" );
+                       opacity_bottom = this._overflow_bottom.css( "opacity" );
+
+                       this._overflow_top.css( "opacity", "0" );
+                       this._overflow_bottom.css( "opacity", "0" );
+
+                       this._overflow_top.css( "-webkit-animation", "ui-overflow-hide" +
+                                       this._getOverflowIndicator( opacity_top ) + " 0.5s 1 ease" );
+                       this._overflow_bottom.css( "-webkit-animation", "ui-overflow-hide" +
+                                       this._getOverflowIndicator( opacity_bottom ) + " 0.5s 1 ease" );
+
+                       this._overflow_showed = false;
+                       this._setOverflowIndicator();
+               },
+
                _add_event: function () {
                        var self = this,
                                $c = this._$clip,
 
                        $v.bind( this._dragEvt, this._dragCB );
 
-                       if ( $c.jqmData("scroll") !== "y" ) {
+                       $v.bind( "keydown", function ( e ) {
+                               var elem,
+                                       elem_top,
+                                       screen_h;
+
+                               if ( e.keyCode == 9 ) {
+                                       return false;
+                               }
+
+                               elem = $c.find(".ui-focus");
+
+                               if ( elem === undefined ) {
+                                       return;
+                               }
+
+                               elem_top = elem.offset().top;
+                               screen_h = $c.offset().top + $c.height() - elem.height();
+
+                               if ( self._softkeyboard ) {
+                                       screen_h -= self._softkeyboardHeight;
+                               }
+
+                               if ( ( elem_top < 0 ) || ( elem_top > screen_h ) ) {
+                                       self.scrollTo( 0, self._sy - elem_top +
+                                               elem.height() + $c.offset().top, 0);
+                               }
+
                                return;
-                       }
+                       });
+
+                       $v.bind( "keyup", function ( e ) {
+                               var input,
+                                       elem,
+                                       elem_top,
+                                       screen_h;
+
+                               if ( e.keyCode != 9 ) {
+                                       return;
+                               }
+
+                               /* Tab Key */
+
+                               input = $( this ).find(":input");
+
+                               for ( i = 0; i < input.length; i++ ) {
+                                       if ( !$( input[i] ).hasClass("ui-focus") ) {
+                                               continue;
+                                       }
+
+                                       if ( i + 1 == input.length ) {
+                                               elem = $( input[0] );
+                                       } else {
+                                               elem = $( input[i + 1] );
+                                       }
+
+                                       elem_top = elem.offset().top;
+                                       screen_h = $c.offset().top + $c.height() - elem.height();
+
+                                       if ( self._softkeyboard ) {
+                                               screen_h -= self._softkeyboardHeight;
+                                       }
+
+                                       if ( ( elem_top < 0 ) || ( elem_top > screen_h ) ) {
+                                               self.scrollTo( 0, self._sy - elem_top +
+                                                       elem.height() + $c.offset().top, 0);
+                                       }
+
+                                       elem.focus();
+
+                                       break;
+                               }
+
+                               return false;
+                       });
 
                        $c.bind( "updatelayout", function ( e ) {
                                var sy,
                                        vh,
-                                       clip_h = $c.height(),
                                        view_h = self._getViewHeight();
 
-                               if ( !clip_h || !view_h ) {
+                               if ( !$c.height() || !view_h ) {
                                        self.scrollTo( 0, 0, 0 );
                                        return;
                                }
 
-                               sy = clip_h - view_h;
+                               sy = $c.height() - view_h;
                                vh = view_h - self._view_height;
 
                                self._view_height = view_h;
-                               self._clip_height = clip_h;
 
-                               if ( vh == 0 || vh > clip_h / 2 ) {
+                               if ( vh == 0 || vh > $c.height() / 2 ) {
                                        return;
                                }
 
-                               if ( self._sy - sy <= -vh ) {
+                               if ( sy > 0 ) {
+                                       self.scrollTo( 0, 0, 0 );
+                               } else if ( self._sy - sy <= -vh ) {
                                        self.scrollTo( 0, self._sy,
                                                self.options.snapbackDuration );
                                } else if ( self._sy - sy <= vh + self.options.moveThreshold ) {
 
                        $( window ).bind( "resize", function ( e ) {
                                var focused,
-                                       clip_h = $c.height(),
                                        view_h = self._getViewHeight();
 
                                if ( $(".ui-page-active").get(0) !== $c.closest(".ui-page").get(0) ) {
                                        return;
                                }
 
-                               if ( !clip_h || !view_h ) {
+                               if ( !$c.height() || !view_h ) {
                                        return;
                                }
 
 
                                /* calibration - after triggered throttledresize */
                                setTimeout( function () {
-                                       self._view_height = self._getViewHeight();
-                                       self._clip_height = $c.height();
-
-                                       if ( self._sy < self._clip_height - self._veiw_height ) {
-                                               self.scrollTo( 0, self._sy,
-                                                       self.options.snapbackDuration );
+                                       if ( self._sy < $c.height() - self._getViewHeight() ) {
+                                               self.scrollTo( 0, $c.height() - self._getViewHeight(),
+                                                       self.options.overshootDuration );
                                        }
                                }, 260 );
 
                                self._view_height = view_h;
-                               self._clip_height = clip_h;
+                       });
+
+                       $( window ).bind( "vmouseout", function ( e ) {
+                               var drag_stop = false;
+
+                               if ( $(".ui-page-active").get(0) !== $c.closest(".ui-page").get(0) ) {
+                                       return;
+                               }
+
+                               if ( !self._dragging ) {
+                                       return;
+                               }
+
+                               if ( e.pageX < 0 || e.pageX > $( window ).width() ) {
+                                       drag_stop = true;
+                               }
+
+                               if ( e.pageY < 0 || e.pageY > $( window ).height() ) {
+                                       drag_stop = true;
+                               }
+
+                               if ( drag_stop ) {
+                                       self._hideScrollBars();
+                                       self._hideOverflowIndicator();
+                                       self._disableTracking();
+                               }
+                       });
+
+                       this._softkeyboard = false;
+                       this._softkeyboardHeight = 0;
+
+                       window.addEventListener( "softkeyboardchange", function ( e ) {
+                               if ( $(".ui-page-active").get(0) !== $c.closest(".ui-page").get(0) ) {
+                                       return;
+                               }
+
+                               self._softkeyboard = ( e.state === "on" ? true : false );
+                               self._softkeyboardHeight = e.height;
                        });
 
                        $c.closest(".ui-page")
                                .one( "pageshow", function ( e ) {
                                        self._view_offset = self._$view.offset().top - self._$clip.offset().top;
+                                       self._view_height = self._getViewHeight();
                                })
                                .bind( "pageshow", function ( e ) {
                                        /* should be called after pagelayout */
                                        setTimeout( function () {
-                                               self._view_height = self._getViewHeight();
-                                               self._clip_height = self._$clip.height();
-
                                                self._set_scrollbar_size();
                                                self._setScrollPosition( self._sx, self._sy );
                                                self._showScrollBars( 2000 );
+                                               self._resetOverflowIndicator();
                                        }, 0 );
                                });
                },
                        }
 
                        if ( this._vTracker ) {
-                               top_btn = $( '<div class="ui-scroll-jump-top-bg ui-btn" data-theme="s">' +
-                                               '<div class="ui-scroll-jump-top"></div></div>' );
-                               $c.append( top_btn );
+                               top_btn = $( '<div class="ui-scroll-jump-top-bg">' +
+                                               '<div data-role="button" data-inline="true" data-icon="jumptop" style="width:37px;height:37px">.</div></div>' );
+                               $c.append( top_btn ).trigger("create");
 
                                top_btn.bind( "vclick", function () {
                                        self.scrollTo( 0, 0, self.options.overshootDuration );
                        }
 
                        if ( this._hTracker ) {
-                               left_btn = $( '<div class="ui-scroll-jump-left-bg ui-btn" data-theme="s">' +
-                                               '<div class="ui-scroll-jump-left"></div></div>' );
-                               $c.append( left_btn );
+                               left_btn = $( '<div class="ui-scroll-jump-left-bg">' +
+                                               '<div data-role="button" data-inline="true" data-icon="jumpleft" style="width:37px;height:37px">.</div></div>' );
+                               $c.append( left_btn ).trigger("create");
 
                                left_btn.bind( "vclick", function () {
                                        self.scrollTo( 0, 0, self.options.overshootDuration );
                        }
                },
 
+               _add_overflow_indicator: function () {
+                       if ( !this.options.overflowEnable ) {
+                               return;
+                       }
+
+                       this._overflow_top = $( '<div class="ui-overflow-indicator-top"></div>' );
+                       this._overflow_bottom = $( '<div class="ui-overflow-indicator-bottom"></div>' );
+
+                       this._$clip.append( this._overflow_top );
+                       this._$clip.append( this._overflow_bottom );
+
+                       this._opacity_top = "0.5";
+                       this._opacity_bottom = "0.5";
+                       this._overflow_showed = false;
+               },
+
                _set_scrollbar_size: function () {
                        var $c = this._$clip,
                                $v = this._$view,
                        }
 
                        if ( this._vTracker ) {
-                               ch = this._clip_height;
-                               vh = this._view_height;
+                               ch = $c.height();
+                               vh = this._getViewHeight();
                                this._maxY = ch - vh;
 
                                if ( this._maxY > 0 ) {
                                        thumb = this._$vScrollBar.find(".ui-scrollbar-thumb");
                                        thumb.css( "height", (ch >= vh ? "0" :
                                                        (Math.floor(ch / vh * 100) || 1) + "%") );
+
+                                       this._overflowAvail = !!thumb.height();
                                }
                        }
                }
                        return this.pos === this.maxPos;
                },
 
+               isAvail: function () {
+                       return !( this.minPos === this.maxPos );
+               },
+
                getRemained: function () {
                        return this.remained;
                },
                                $( this ).scrolllistview();
                        } else {
                                var st = $( this ).jqmData("scroll"),
-                                       dir = st && ( st.search(/^[xy]/) !== -1 ) ? st.charAt(0) : null,
+                                       dir = st && ( st.search(/^[xy]/) !== -1 ) ? st : null,
+                                       content = $(this).hasClass("ui-content"),
                                        opts;
 
                                if ( st === "none" ) {
 
                                opts = {
                                        direction: dir || undefined,
+                                       overflowEnable: content,
                                        scrollMethod: $( this ).jqmData("scroll-method") || undefined,
                                        scrollJump: $( this ).jqmData("scroll-jump") || undefined
                                };