1
votes

I am currently working on a page. I have used polymer's paper-drawer-panel and paper-header-panel combination.

Basically there are two containers, the inner container needs to be scrolled horizontally while the outer container needs to be scrolled vertically. When I have not used the paper-header-panel, the behavior is appropriate. You can see the demo here. If you open this site on a mobile browser (chrome or others/haven't checked with Safari) or on the mobile simulator in chrome, I can scroll both horizontally as well as vertically. This is the behavior I have expected.

But, when I add in the paper-header-panel (part of my custom element <app-layout>), I am able to scroll horizontally (in a mobile browser) but when I touch an element present in the horizontally scrollable div and try to scroll it vertically as in the previous case, the vertical scroll doesn't work anymore. The demo is present here.

The relevant source code for the app-layout element is as below.

html -

<dom-module id="app-layout">

  <link rel="import" type="css" href="app-layout.css">

  <template>

    <paper-drawer-panel id="drawerPanel" responsive-width="1024px" drawer-width="280px">

      <paper-header-panel class="list-panel" drawer>

        <!-- List Toolbar -->
        <div class="paper-header has-shadow layout horizontal center" id="navheader">
        </div>

        <!-- Menu -->
        <div class="left-drawer">
        <paper-menu class="list" selected="0" on-iron-activate="_listTap">
        <template is="dom-repeat" items="{{menus}}">
        <paper-item role="menu"><iron-icon class="menuitems" icon$={{item.icon}}></iron-icon><span>{{item.label}}</span></paper-item>
        </template>
        </paper-menu>
        </div>
      </paper-header-panel>

      <paper-header-panel class$="{{positionClass}}" main mode="{{mainMode}}">

        <!-- Main Toolbar -->
        <paper-toolbar class$="{{toolbarClass}}">
          <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
          <div style="width:60px" id="app-image"><iron-image style="width:40px; height:40px; background-color: lightgray;"
      sizing="contain" preload fade src= "/images/app-icon-110.png"></iron-image></div>
          <div hidden$="{{_isMobile}}" class="flex">{{label}}</div>
          <div class="flex"></div>
          <paper-icon-button icon="search" on-tap="toggleSearch"></paper-icon-button>
          <paper-icon-button icon="more-vert"></paper-icon-button>
        </paper-toolbar>

        <div class="content">

          <paper-material>
            <content select=".main-content"></content>
          </paper-material>

        </div>

      </paper-header-panel>

    </paper-drawer-panel>

  </template>
</dom-module>

CSS -

* { 
    -moz-box-sizing: border-box; 
    -webkit-box-sizing: border-box; 
     box-sizing: border-box; 
}
:host {
    width: 100%;
    height: 100%;
    -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
    display: block;
}


#drawerPanel {
    --paper-drawer-panel-left-drawer-container: {
      background-color: #eee;
    };
}

paper-header-panel {
  background-color: #eee;
}

paper-toolbar {
  background-color: #00bcd4;
}

.left-drawer {
  background-color: #eee;
}

paper-header-panel .content {
  height: 100%;
}

paper-header-panel[mode=cover] .content {
  padding: 0 90px 0 0px;
  height: 100%;
}

paper-header-panel {
  --paper-header-panel-cover-container: {
    height: 100%;
    left: 90px;
  };
}

paper-header-panel[mode=cover] paper-toolbar {
  color: #fff;
  font-size: 20px;
  font-weight: 400;
  padding-right: 16px;
}

.paper-header-panel paper-toolbar #app-image {
  margin-left: -15px;
}

paper-material {
  overflow-y: auto;
  height: auto;
  background-color: #fff;
  z-index: 1;
}

paper-header-panel[mode=cover] paper-material {
  max-width: 1024px;
  margin: 64px auto;
}
2
Strange -- vertical scroll only works from the far left side on my tablet. if you look at this image i took from a desktop browser s28.postimg.org/mrocolqy5/Capture.png the content is not sitting inside properly as you have a class -- main-content --. isnt there a content tag in polymer?? - Tasos
Ok i think i found a fix for you -- take out (padding: 0 90px 0 0px; */) from (.left-edged[mode=cover].app-layout .content.app-layout) have a look at this screenshot -- s11.postimg.org/z8pobsdlf/Capture.png -- however your content is still sitting on the header as you have an extra large header - Tasos
The content is designed to look that way to be scrollable horizontally. It is supposed to look differently on desktop, tablets and phones. On desktops where side drawer is open, main content will be stationed right next to it, on tablets where drawer is closed, it will be a card layout where the left and right sides are open and on mobile where it is narrow, it will be a simple layout. I have used <content select=".main-content"> so the main-content class items go into the insertion point inside the <app-layout> element. - Aravind
ok i understand. there seems to be a problem with the cards. you can scroll in between the cards (Vegetarian recipes) headings. what about placing the whole content inside a core-item to make the whole thing scrollable - Tasos
That sounds interesting. But then, wouldn't the individual card items in the horizontally scrollable div become unclickable? I would have to disable to default event handling for the paper-items, I think - Aravind

2 Answers

1
votes

From our Comments,

As an alternative solution until you find the problem you can test using Iscroll 5 for the horizontal scroll of the cards and see if it works ok within the App.

Ive used Iscroll 5 for my App using both horizontal and vertical scrolls with 100's of Items and its fast on Polymer. I haven't had any performance issues so far although i turned off bounce in iscroll options eg ,bounce: false to get that extra performance boost

If you have Click events for the Cards then add ,click:true to the Iscroll options

Iscroll 5 guide here http://iscrolljs.com/

The demo creates the Iscroll for any row when the user scrolls horizontally there to save resources and the Original Demo in my comments was for JQM framework which has built in Swipe detection.

In Polymer version 0.5 it has built in Touch functionality not sure about version 1 yet but i never used yet https://www.polymer-project.org/0.5/docs/polymer/touch.html

For Polymer i created another Demo that Uses Javascript Touch events to detect horizontal movements only so you wont need any Other Touch gesture Pluggings to add to the App

Demo I set a 5sec delay for the code to initialize. Pretty much all the code is for handling Touch. In the function slide(x) { is the Iscroll code about 10 lines

http://codepen.io/anon/pen/pJRmLo

Code

    var slides = 17; //how many items in a row
    var totalwidth = slides * 80; //times that by the width of each item in a row

    $(".scroller").css("width", totalwidth+"px"); //set the total width of the horizontal wrapper

   // touch function 
    var startPos;
        var handlingTouch = false;
        var itemis;
        setTimeout(function() {

        document.addEventListener('touchstart', function(e) {
          // Is this the first finger going down? 

          if (e.touches.length == e.changedTouches.length) {
            startPos = {
              x: e.touches[0].clientX,
              y: e.touches[0].clientY
            };
          }
        });

        document.addEventListener('touchmove', function(e) {
          // If this is the first movement event in a sequence:
          if (startPos) {
            // Is the axis of movement horizontal?
            if (Math.abs(e.changedTouches[0].clientX - startPos.x) > Math.abs(e.changedTouches[0].clientY - startPos.y)) {
              handlingTouch = true;
              e.preventDefault();
              onSwipeStart(e);
            }
            startPos = undefined;
          } else if (handlingTouch) {
            e.preventDefault();
            onSwipeMove(e);
          }
        });

        document.addEventListener('touchend', function(e) {
          if (handlingTouch && e.touches.length == 0) {
            e.preventDefault();
            onSwipeEnd(e);
            handlingTouch = false;
          }
        });



        function slide(x) {

    var cclass = $(itemis).attr("class")
    var ccclass = "."+cclass;
    var newis = $(itemis).attr("data-id"); 

    if (newis != "running") {
    var cclass = new IScroll(ccclass, {
        eventPassthrough: true, 
        scrollX: true, 
        scrollY: false, 
        preventDefault: false
        });
    cclass.scrollBy(-50, 0, 500);
    //control here how many pixels to auto scroll uppon activating the scroll eg -50px
    $(itemis).attr("data-id","running")   
        }
        }

        var swipeOrigin, x, itempos;
        function onSwipeStart(e) {

    // find what element is been touched. In your case it may be closest("swElement") but you need to test

          itemis = $(e.target).closest("div");
          // when touching over an element get its target, in this case the closest div of the row

          swipeOrigin = e.touches[0].clientX;
        }
        function onSwipeMove(e) {
          x = e.touches[0].clientX - swipeOrigin;
         // slide(x);
        }
        function onSwipeEnd(e) {

        //On Touch End if x (distance traveled to the right) is greater than +35 pixels then slide element  +100 pixels.

          if (x > 35) { 
        slide(0);
          }
          else {
          slide(0);
        }
        }
        }, 5000);

The above touch function I originally used for transforming/moving list items by touch drag similarly to Gmail App, for JQM and Polymer list items. Can be used for anything horizontally in the case of Iscroll is not really used in that way but it basically says if you touch move horizontally over a row activate the Iscroll for that row

Check my demo in the Link for an alternative use of the function.

jQuery touchSwipe event on element prevents scroll

1
votes

The problem arises because on mobiles, horizontal scrolling is disabled when vertical scrolling is active and vice-versa. I have solved this for now using Tasos suggestion to use iScroll. I used polymer's async function to initialize the scrollers with a delay. Here is the code I have used as part of polymer-ready.

<script>
Polymer ({
      ...
      ...
      ready:function() {
        this.async(function() {
            this.setScroll();
            }, null, 300);
            },
        setScroll: function() {
            var nodeList = document.querySelectorAll('.wrapper');
            if(nodeList.length == 0) {
                this.async(function() { this.setScroll(); }, null, 300);
            }
            for (var i=0; i<nodeList.length; i++) {
//              this.setScrollDirection ('y', nodeList[i]);
                nodeList[i].id = 'wrapper'+i;
                var myScroll = new IScroll('#'+nodeList[i].id, { eventPassthrough: true, scrollX: true, scrollY: false, preventDefault: false });
//              myScroll.scrollBy(-50, 0, 500);
            }
            }
          })();
</script>

I was also able to use Polymers track gesture as mentioned in the documentation.

Listening for certain gestures controls the scrolling direction for touch input. For example, nodes with a listener for the track event will prevent scrolling by default. Elements can be override scroll direction with this.setScrollDirection(direction, node), where direction is one of 'x', 'y', 'none', or 'all', and node defaults to this.

state - a string indicating the tracking state:
start - fired when tracking is first detected (finger/button down and moved past a pre-set distance threshold)
track - fired while tracking
end - fired when tracking ends
x - clientX coordinate for event
y - clientY coordinate for event
dx - change in pixels horizontally since the first track event
dy - change in pixels vertically since the first track event
ddx - change in pixels horizontally since last track event
ddy - change in pixels vertically since last track event
hover() - a function that may be called to determine the element currently being hovered

I have used (dx > dy) to understand whether it is a horizontal or vertical swipe and then enabled horizontal and vertical swiping specifically as per the case. This worked but I liked the bounce and the other options provided by iScroll and besides its only 4KB minified and gzipped. So, I decided to go with iScroll.

[Note: jQuery is not needed to use iScroll. It is an independent script]