1. #11
    Ext JS Premium Member SimonFlack's Avatar
    Join Date
    Jul 2010
    Location
    Norway
    Posts
    241
    Vote Rating
    3
    SimonFlack is on a distinguished road

      0  

    Default


    This plugin was just what I needed. Although I needed it for paging.

    Here is my modified version.



    Usage:

    Code:
    plugins: [new mobile.plugins.ListPullPager({
    		previousFn: function(cb,scope){
    		    mobile.commissions.store.previousPage();
    		    cb.call(this);
    		},
    		nextFn: function(cb,scope){
    		    mobile.commissions.store.nextPage(); 
    		    cb.call(this);
    		}
    	    })]
    Plugin:

    Code:
    Ext.apply(Ext.anims, {
        rotate: new Ext.Anim({
            autoClear: false,
            out: false,
            before: function(el) {
                var d = '';
                if (this.dir == 'ccw'){
                  d = '-';
                }
    
                this.from = {
                    '-webkit-transform': 'rotate('+d+''+this.fromAngle+'deg)'
                };
    
                this.to = {
                    '-webkit-transform': 'rotate('+d+''+this.toAngle+'deg)'
                };
                            
            }
        })
    });  
    
    Ext.ns('mobile.plugins');
    
    mobile.plugins.ListPullPager = Ext.extend(Ext.util.Observable, {
      langPullPrevious: 'Pull down to load previous...',
      langReleasePrevious: 'Release to load previous...',
      langPullNext: 'Pull up to load next...',
      langReleaseNext: 'Release to load next...',
      langLoading: 'Loading...',
     
      loading: false,
      //define the functions to call for loading.
      previousFn: undefined,
      nextFn: undefined,
      // private
      init: function(cmp){
        this.cmp = cmp;
        this.lastUpdate = new Date();
        cmp.loadingText = undefined;
        cmp.on('render', this.initPullHandler, this);
        if (!this.previousFn || !this.nextFn){
          cmp.getStore().on('load', this.reloadComplete, this);
        }
      },
      // private
      initPullHandler: function(){
        //Previous
        this.previousTpl = new Ext.XTemplate(
          '<div class="pullprevious" style="height: {h}; text-align: bottom;">'+
            '<div class="msgwrap" style="height: 75px; bottom: 0px; position: relative;">'+
              '<span class="arrow {s}"></span>'+
              '<span class="msg">{m}</span>'+
            '</div>'+
          '</div>');
        this.previousEl = this.previousTpl.insertBefore(this.cmp.scroller.el, {h:0,m:this.langPullPrevious,l:this.lastUpdate}, true);
        this.previousEl.hide();
        Ext.Element.cssTranslate(this.previousEl, {x:0, y:+75});
        //this.cmp.scroller.on('offsetchange', this.handlePrevious, this);
        
        //Next
        this.nextTpl = new Ext.XTemplate(
          '<div class="pullnext" style="height: {h}; text-align: bottom;">'+
            '<div class="msgwrap" style="height: 75px; bottom: 0px; position: relative;">'+
              '<span class="arrow {s}"></span>'+
              '<span class="msg">{m}</span>'+
            '</div>'+
          '</div>');
        this.nextEl = this.nextTpl.insertAfter(this.cmp.scroller.el, {h:0,m:this.langPullNext,l:this.lastUpdate}, true);
        this.nextEl.hide();
        Ext.Element.cssTranslate(this.nextEl, {x:0, y:-75});
        
        
        this.cmp.scroller.on('offsetchange', this.handleOffsettChange, this);
      },
      
      handleOffsettChange: function(scroller, offset) {
        if (scroller.direction === 'vertical' && !this.loading){
          
          var heightOfList = scroller.size.height - scroller.containerBox.height;
          
          if (offset.y > 0){
            //console.log('up');
            this.handlePrevious(scroller, offset, heightOfList);
          }
          
          if (offset.y < (heightOfList * -1)) {
            //console.log('down');
            this.handleNext(scroller, offset, heightOfList);
          }
        }
      },
      
      //private
      handlePrevious: function(scroller, offset, heightOfList){
        if (scroller.direction === 'vertical' && !this.loading){
          if (offset){
            Ext.Element.cssTranslate(this.previousEl, {x:0, y:offset.y-75});
            if (offset.y > 75){
              // state 1
              if (this.state !== 1){
                this.prevState = this.state;
                this.state = 1;
                this.previousTpl.overwrite(this.previousEl, {h:offset.y,m:this.langReleasePrevious,l:this.lastUpdate});
                Ext.Anim.run(this.previousEl.select('.arrow').first(),'rotate',{dir:'ccw',fromAngle:0,toAngle:180});
              }
            }else if (!scroller.isDragging()){
              // state 3
              if (this.state !== 3){
                this.prevState = this.state;
                this.state = 3;
                if (this.prevState == 1){
                  this.loading = true;
                  this.lastUpdate = new Date();
                  this.previousEl.hide();
                  if (this.previousFn){
                    this.previousFn.call(this,this.previousComplete,this);
                  }else{
                    this.cmp.getStore().load();
                  }
                }
              }
            }else{
              // state 2
              if (this.state !== 2){
                this.prevState = this.state;
                this.state = 2;
                this.previousTpl.overwrite(this.previousEl, {h:offset.y,m:this.langPullPrevious,l:this.lastUpdate});
                this.previousEl.show();
                if (this.prevState == 1){
                  Ext.Anim.run(this.previousEl.select('.arrow').first(),'rotate',{dir:'cw',fromAngle:180,toAngle:0});
                }
              }
            }
          }
        }
      },
      handleNext: function(scroller, offset, heightOfList){
        if (scroller.direction === 'vertical' && !this.loading){
          if (offset){
            Ext.Element.cssTranslate(this.nextEl, {x:0, y:offset.y});
            if (offset.y < ((heightOfList + 75)*-1)){
              // state 1
              if (this.state !== 1){
                this.prevState = this.state;
                this.state = 1;
                this.nextTpl.overwrite(this.nextEl, {h:offset.y,m:this.langReleaseNext,l:this.lastUpdate});
                Ext.Anim.run(this.nextEl.select('.arrow').first(),'rotate',{dir:'ccw',fromAngle:180,toAngle:0});
              }
            }else if (!scroller.isDragging()){
              // state 3
              if (this.state !== 3){
                this.prevState = this.state;
                this.state = 3;
                if (this.prevState == 1){
                  this.loading = true;
                  this.lastUpdate = new Date();
                  this.nextEl.hide();
                  if (this.nextFn){
                    this.nextFn.call(this,this.nextComplete,this);
                  }else{
                    this.cmp.getStore().load();
                  }
                }
              }
            }else{
              // state 2
              if (this.state !== 2){
                this.prevState = this.state;
                this.state = 2;
                this.nextTpl.overwrite(this.nextEl, {h:offset.y,m:this.langPullNext,l:this.lastUpdate});
                this.nextEl.show();
                if (this.prevState == 1){
                  Ext.Anim.run(this.nextEl.select('.arrow').first(),'rotate',{dir:'cw',fromAngle:180,toAngle:0});
                }
              }
            }
          }
        }
      },
      //private
      previousComplete: function(){
        this.loading = false;
        this.lastUpdate = new Date();
        this.previousTpl.overwrite(this.previousEl, {h:0,m:this.langPullPrevious,l:this.lastUpdate});
      },
      nextComplete: function(){
        this.loading = false;
        this.lastUpdate = new Date();
        this.nextTpl.overwrite(this.nextEl, {h:0,m:this.langPullNext,l:this.lastUpdate});
      }
    });
    
    Ext.preg('listpullpager', mobile.plugins.ListPullPager);
    CSS

    Code:
    div.pullprevious, div.pullprevious div.msgwrap {
      background-color: #e1e1e1 !important;
    }
    
    div.pullprevious span.arrow {
      width: 32px;
      height: 60px;
      position: absolute;
      top: 0;
      left: 10px;
      background-image: url('../images/blackArrow.png');
      background-repeat: no-repeat;
      margin: 10px 0 0 25px;
    }
    
    div.loadingspacer span.loading {
      width: 32px;
      height: 60px;
      position: absolute;
      top: 0;
      left: 10px;
      background-image: url('../images/loader.gif');
      background-repeat: no-repeat;
      background-position: 0 7px;
    }
    
    div.pullprevious span.msg, div.loadingspacer span.msg {
      width: 80%;
      text-align: center;
      font-size: 0.9em;
      position: absolute;
      top: 12px;
      left: 40px;
      margin: 5px 0 5px 40px; 
      font-weight: bold;
    }
    
    div.pullprevious span.lastupdate {
      width: 80%;
      text-align: center;
      font-size: 0.7em;
      position: absolute;
      top: 25px;
      left: 40px;
      margin: 15px 0 5px 40px;
    }
    
    div.pullnext, div.pullnext div.msgwrap {
      background-color: #e1e1e1 !important;
    }
    
    div.pullnext span.arrow {
      width: 32px;
      height: 60px;
      position: absolute;
      top: 0;
      left: 10px;
      background-image: url('../images/blackArrow.png');
      background-repeat: no-repeat;
      margin: 10px 0 0 25px;
      -webkit-transform: rotate(180deg);
    }
    
    div.pullnext span.msg, div.loadingspacer span.msg {
      width: 80%;
      text-align: center;
      font-size: 0.9em;
      position: absolute;
      top: 12px;
      left: 40px;
      margin: 5px 0 5px 40px; 
      font-weight: bold;
    }
    
    div.pullnext span.lastupdate {
      width: 80%;
      text-align: center;
      font-size: 0.7em;
      position: absolute;
      top: 25px;
      left: 40px;
      margin: 15px 0 5px 40px;
    }
    Figured I'd post it here just incase its of value to somebody.

  2. #12
    Sencha User
    Join Date
    Apr 2008
    Location
    Buenos Aires, Argentina
    Posts
    67
    Vote Rating
    0
    elmasse is on a distinguished road

      0  

    Default


    Excellent work guys! Just one suggestion: Instead of having different functions to be attached for previousFn and nextFn why not using events? So we can attach as many fn as we need and also you can create a before/after events for each one of those.

  3. #13
    Sencha - Community Support Team VinylFox's Avatar
    Join Date
    Mar 2007
    Location
    Baltimore, MD
    Posts
    1,501
    Vote Rating
    7
    VinylFox will become famous soon enough VinylFox will become famous soon enough

      0  

    Default


    Quote Originally Posted by elmasse View Post
    ...Instead of having different functions to be attached for previousFn and nextFn why not using events? So we can attach as many fn as we need and also you can create a before/after events for each one of those.
    Excellent idea. Will do.

  4. #14
    Sencha User
    Join Date
    Sep 2008
    Location
    Netherlands
    Posts
    106
    Vote Rating
    1
    buz is on a distinguished road

      0  

    Default


    In that case maybe you can make it a plugin for every panel. I think it would be more useful, because other panels without a list can be updated on request to.

    Maybe you could extend this component and create a "PullToSearch" =) would be great. (if you have time)

  5. #15
    Sencha - Community Support Team VinylFox's Avatar
    Join Date
    Mar 2007
    Location
    Baltimore, MD
    Posts
    1,501
    Vote Rating
    7
    VinylFox will become famous soon enough VinylFox will become famous soon enough

      0  

    Default


    I have updated this to fire a 'released' event instead of calling a static method. Check out Github for the most recent version and the readme file on how to use it now.

    https://github.com/VinylFox/Ext.ux.t...istPullRefresh

    Also check out my blog for a write up - http://www.vinylfox.com/list-pull-re...-sencha-touch/

  6. #16
    Touch Premium Member
    Join Date
    Feb 2011
    Posts
    57
    Vote Rating
    0
    mvoss is on a distinguished road

      0  

    Default Loading mask

    Loading mask


    Hi,
    nice work. It works nice! One little problem with the loading mask though. It seems this plugin hides the lists loading mask. I am guessing this is because you do not want the loading mask when the list is updated with this plugin (by pulling). However I would like to show the loading mask the first time the list is loaded. Is this possible?

    regards,
    Markus

  7. #17
    Sencha - Community Support Team VinylFox's Avatar
    Join Date
    Mar 2007
    Location
    Baltimore, MD
    Posts
    1,501
    Vote Rating
    7
    VinylFox will become famous soon enough VinylFox will become famous soon enough

      0  

    Default


    That's a good point Markus, Ill look into how to fix that.

  8. #18
    Touch Premium Member
    Join Date
    Feb 2011
    Posts
    57
    Vote Rating
    0
    mvoss is on a distinguished road

      0  

    Default


    Hi,

    did you have any time to have a look at this? I think this would be a nice feature to have!

    Regards,
    Markus

  9. #19
    Sencha User
    Join Date
    May 2011
    Posts
    143
    Vote Rating
    0
    rockinthesixstring is on a distinguished road

      0  

    Default


    I've got this working, however when I pull down, the grey area (#e1e1e1) is only as tall as the text, and above the grey is the Sencha off white again. How can I make it so that the grey goes all the way to the top, no matter how far down I pull?

    Thanks.

  10. #20
    Sencha Premium Member dawesi's Avatar
    Join Date
    Mar 2007
    Location
    Melbourne, Australia (aka GMT+10)
    Posts
    1,083
    Vote Rating
    44
    dawesi has a spectacular aura about dawesi has a spectacular aura about

      0  

    Default


    Quote Originally Posted by mvoss View Post
    Hi,
    nice work. It works nice! One little problem with the loading mask though. It seems this plugin hides the lists loading mask. I am guessing this is because you do not want the loading mask when the list is updated with this plugin (by pulling). However I would like to show the loading mask the first time the list is loaded. Is this possible?

    regards,
    Markus

    I guess you could always add the plugin using the load event until it's tweaked?!
    Teahouse Training Company
    Official Certified Sencha Trainer

    Australia / New Zealand / Singapore / Hong Kong & APAC



    SenchaWorld.com - Sencha webinars, videos, etc
    SenchaForge.org - (coming soon)
    TeahouseHQ.com - Sencha ecosystem training portal

    Code Validation : JSLint | JSONLint | JSONPLint

Similar Threads

  1. Ext.ux.touch.SwipeTabs
    By VinylFox in forum Sencha Touch 1.x: Examples and Showcases
    Replies: 24
    Last Post: 28 Jun 2012, 1:23 AM
  2. Ext Designer for Touch
    By Frank R in forum Sencha Touch 1.x: Discussion
    Replies: 6
    Last Post: 11 Feb 2012, 12:53 PM
  3. Ext JS and Sencha Touch!
    By mcamer in forum Sencha Touch 1.x: Discussion
    Replies: 8
    Last Post: 1 Dec 2010, 10:19 AM
  4. Sencha Touch on iPhone v1 / iPod touch v1 ?
    By palnap in forum Sencha Touch 1.x: Discussion
    Replies: 4
    Last Post: 28 Oct 2010, 5:30 PM
  5. Ext Touch Core anyone?
    By mystix in forum Sencha Touch 1.x: Discussion
    Replies: 1
    Last Post: 11 Jun 2010, 4:52 AM

Thread Participants: 16