I seem unable to get iron-scroll-threshold working with an iron-list inside an app-header-layout.
Note that for compatibility reasons with some 3rd party components I still use Polymer 1 (1.11.3).
Here is a reduced code example:
<app-location route="{{route}}"></app-location>
<app-route route="{{route}}" pattern="/app/:view" data="{{routeData}}" tail="{{subRoute}}"></app-route>
<app-route route="{{subRoute}}" pattern="/:id" data="{{idData}}" active="{{onDetailPage}}"></app-route>
<app-drawer-layout>
<app-drawer slot="drawer" swipe-open>
<app-toolbar class="navToolbar">
<a href="/app/foo" drawer-toggle>Menu Item 1</a>
</app-toolbar>
</app-drawer>
<app-header-layout>
<app-header class="mainHeader" condenses fixed effects="resize-title blend-background waterfall" slot="header">
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<h4 condensed-title>Summary</h4>
</app-toolbar>
<app-toolbar class="tall">
<h1 main-title>Welcome</h1>
</app-toolbar>
</app-header>
<iron-pages selected="[[routeData.view]]" attr-for-selected="name" fallback-selection="home">
<time-line name="foo"></time-line>
<!-- other elements / pages -->
</iron-pages>
</app-header-layout>
</app-drawer-layout>
The element I want to scroll in is:
<dom-module id="time-line">
<template>
<app-location route="{{route}}"></app-location>
<app-route route="{{route}}" pattern="/app/:view" data="{{routeData}}" tail="{{subRoute}}"></app-route>
<app-route route="{{subRoute}}" pattern="/:id" data="{{idData}}" active="{{onDetailPage}}"></app-route>
<iron-ajax id="loadData" attr="/api/foo" handle-as="json" on-response="dataLoaded"></iron-ajax>
<style is="custom-style"></style>
<iron-scroll-threshold id="threshold" on-lower-threshold="_loadMoreData">
<iron-list id="list" items="[[datas]]" as="data" scroll-target="threshold">
<template>
<div class="layout vertical">
<p>[[data]]</p>
</div>
</template>
</iron-list>
</iron-scroll-threshold>
</template>
<script>
Polymer({
is : "time-line",
properties: {
pagee: {
type: Number,
value: -1
},
datas: {
type: Array,
value: []
}
},
init: function() {
this.pagee = 0;
this.$.loadData.params = { "page" : this.pagee };
this.$.loadData.generateRequest();
},
dataLoaded: function(e) {
if (!this.datas) this.datas = [];
if (e.detail.response.length > 0) {
e.detail.response.forEach(function(element) {
this.push("datas", element);
}.bind(this));
this.$.threshold.clearTriggers();
}
},
_loadMoreData: function() {
this.pagee++;
this.$.loadData.params = { "page" : this.pagee };
this.$.loadData.generateRequest();
}
});
</script>
</dom-module>
I just found the solution by accident (and by reading the docs for the x'th time):
<iron-scroll-threshold scroll-target="document" id="threshold" on-lower-threshold="_loadMoreData">
scroll-target="document" was the missing part.
Edit 1
Wait... I have two elements with ìron-list and iron-scroll-threshold, and on both I have set scroll-target="document".
Now the effect is that, when I scroll in one of those elements, the method _loadMoreData is fired for both elements. Weird.
Edit 2
I hacked a workaround which seems to "fix" the issue:
Define this function:
function resetDocumentScrollers() {
var ist = document.querySelectorAll("iron-scroll-threshold");
[].forEach.call(ist, function(e) {
e.scrollTarget = null;
});
}
And in my custom init() method of every element, I call:
resetDocumentScrollers();
this.$.threshold.scrollTarget = "document";
How ugly.
Related
I am trying to implement the hash scroll to in the following app page.
I am setting the id of the function-detail to the name of the function. When I add the hash to the URL of the function named, I do not get a scroll to in the contents of the app-header=layout. What am I missing?
<iron-location id="sourceLocation" query="{{query}}" hash="{{hash}}"></iron-location>
<iron-query-params id="sourceParams" params-string="{{query}}" params-object="{{params}}"></iron-query-params>
<iron-ajax auto="true"
url="/v1/resources/xqdoc"
params="[[params]]"
handle-as="json"
last-response="{{result}}"></iron-ajax>
<app-drawer-layout>
<app-drawer slot="drawer">
<app-toolbar>
<div main-title>Modules</div>
</app-toolbar>
<section>
<paper-listbox attr-for-selected="item-name" selected="{{selectedSuggestionId}}" fallback-selection="None">
<h3>Libraries</h3>
<template is="dom-repeat" items="[[result.modules.libraries]]">
<paper-item item-name="[[item.uri]]">[[item.uri]]</paper-item>
</template>
<h3>Mains</h3>
<template is="dom-repeat" items="[[result.modules.main]]">
<paper-item item-name="[[item.uri]]">[[item.uri]]</paper-item>
</template>
</paper-listbox>
<div style="margin-bottom:90px;width:100%;"></div>
</section>
</app-drawer>
<app-header-layout>
<app-header slot="header" reveals effects="waterfall">
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div main-title>xqDoc</div>
<paper-toggle-button checked="{{showHealth}}">Show Documentation Health</paper-toggle-button>
</app-toolbar>
</app-header>
<section>
<template is="dom-if" if="{{result.response.uri}}">
<xqdoc-module show-health="[[showHealth]]" item="{{result.response}}"></xqdoc-module>
<template is="dom-repeat" items="{{result.response.imports}}">
<import-detail item="{{item}}"></import-detail>
</template>
<template is="dom-repeat" items="{{result.response.variables}}">
<variable-detail show-health="[[showHealth]]" item="{{item}}" params="{{params}}" hash="{{hash}}"></variable-detail>
</template>
<template is="dom-repeat" items="{{result.response.functions}}">
<function-detail id$="[[item.name]]" show-health="[[showHealth]]" item="{{item}}" params="{{params}}" hash="{{hash}}"></function-detail>
</template>
</template>
<paper-card>Created by xqDoc version [[result.response.control.version]] on [[result.response.control.date]]</paper-card>
<div style="margin-bottom:200px;height:150px;width:100%;"></div>
</section>
</app-header-layout>
</app-drawer-layout>
Here is an image of the developer window.
Thanks to AmmpPT, I found my answer:
I used this.shadowRoot.querySelector('#id') to get the element and then used scrollIntoView()
static get properties() {
return {
result: { type: Object, notify: true },
params: { type: Object, notify: true },
hash: { type: String, notify: true, observer: '_hashChanged' },
showHealth: { type: Boolean, notify: true, value: false },
selectedSuggestionId: { type: String, notify: true, observer: '_moduleSelected' }
};
}
_hashChanged(newValue, oldValue) {
var a= '#' + newValue;
var b = this.shadowRoot.querySelector(a);
if (b) {
b.scrollIntoView();
}
}
I'm using Polymer 1.x, and I have an <iron-selector> with generated links. I would like for one of my links to scroll to a <div>. However, I cannot achieve this successfully as the link is intercepted by the <iron-pages>. Here is what I have tried so far:
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{routeData}}"
tail="{{subroute}}"></app-route>
<iron-selector role="navigation" class="drawer-list" selected="[[categoryName]]" attr-for-selected="name">
<template is="dom-repeat" items="[[categories]]" as="category" initial-count="4">
<a name="[[category.name]]" href="[[category.link]]">[[category.title]]</a>
</template>
</iron-selector>
<section id="contactSection" class="home-contact ss-style-triangles">
<div class="container">
<div class="contact-wrap">
<h1>Contact</h1>
</div>
</div>
</section>
<iron-pages role="main" selected="[[page]]" attr-for-selected="name" selected-attribute="visible" fallback-selection="404">
<!-- home view -->
<cass-home name="home"></cass-home>
<cass-why name="whyChooseUs" route="{{subroute}}"></cass-why>
<cass-partner name="partner" route="{{subroute}}"></cass-partner>
<cass-404-warning name="404"></cass-404-warning>
</iron-pages>
Then in JavaScript:
var categoryList = [
{
name: 'home',
title: 'Accueil',
link: '/home',
},
{
name: 'home',
title: 'Home',
link: '/home',
},
{
name: 'b2b',
title: 'Company',
link: '/b2b',
},
{
name: 'login',
title: 'Connection',
link:'/login'
},
{
name: 'contact',
title: 'Contact',
link:'javascript:document.querySelector("#contactSection").scrollIntoView();'
}
];
The is linked to an to set the core part of my
However, as it is in the local DOM, it's not detecting the #contactSection. I also tried using a function and registering a listener, but unsuccessfully.
Any hints?
You can workaround that problem by imperatively scrolling the <div> into view with a listener on the anchor's tap event:
About
Contact
// <script>
_onTapAnchor: function(e) {
e.preventDefault();
var anchor = e.target.attributes.href.value;
this.$$(anchor).scrollIntoView();
}
Notes:
e.target is the <a> tag, which has an attributes map, containing the raw value of href (#contactSection as opposed to http://localhost:8080/#contactSection).
We take e.target.attributes.href.value (e.g., #contactSection) and query the local DOM for it with this.$$(...) -- shorthand for Polymer.dom(this.root).querySelector(...).
We then take the result of the previous call (which is a <div>), and call scrollIntoView() on it, which brings the <div> into the viewport.
I am trying to access same data in single element for two times, one for desktop navigation and one for responsive navigation(drawer toolbar). For this I use two content tags but it takes only one. In this this case what to do
<app-drawer-layout force-narrow>
<app-drawer id="drawer">
<app-toolbar></app-toolbar>
<!-- Nav on mobile: side nav menu -->
<paper-menu selected="{{selected}}" attr-for-selected="name">
<template is="dom-repeat" items="{{items}}">
<paper-item name="{{item}}">{{item}}</paper-item>
</template>
</paper-menu>
</app-drawer>
<app-header-layout>
<app-header class="main-header">
<app-toolbar>
<paper-icon-button class="menu-button" icon="menu" drawer-toggle hidden$="{{wideLayout}}"></paper-icon-button>
</app-toolbar>
<app-toolbar class="tabs-bar" hidden$="{{!wideLayout}}">
<!-- Nav on desktop: tabs -->
<paper-tabs selected="{{selected}}" attr-for-selected="name" bottom-item>
<template is="dom-repeat" items="{{items}}">
<paper-tab name="{{item}}">{{item}}</paper-tab>
</template>
</paper-tabs>
</app-toolbar>
</app-header>
</app-header-layout>
</app-drawer-layout>
<iron-media-query query="min-width: 600px" query-matches="{{wideLayout}}"></iron-media-query>
Polymer code:
Polymer({
is: 'x-app',
properties: {
selected: {
type: String,
value: 'Item One'
},
wideLayout: {
type: Boolean,
value: false,
observer: 'onLayoutChange',
},
items: {
type: Array,
value: function() {
return ['Item One', 'Item Two', 'Item Three', 'Item Four'];
}
}
},
onLayoutChange: function(wide) {
var drawer = this.$.drawer;
if (wide && drawer.opened) {
drawer.opened = false;
}
}
});
I have this type of code. What should I do to add menu element without using array. I want to add them separately from index at both app-header and app-drawer. but in index it should written one time as shown below.
<wt-header logo="logo url" enable-menu="true" enable-topbar="false">
<wt-menu>
<wt-tab name="TabName" action="http://example.com/action" />
<wt-tab name="TabName1" action="http://example.com/action2" />
<wt-tab name="TabName3" action="http://example.com/action3" />
</wt-menu>
</wt-header>
I think you need to provide it twice. <content> doesn't "produce" what you pass to an element, it just projects the content - <content> is just a slot where the passed content is shown.
If you want to provide it twice, then you need to add a select=".some" to at least one <content> to define what part of the projected content (the one that matches the selector .some) should be projected to this <content select=".some"> and what content should be projected to the other <content> element.
An alternative approach is to pass the content within a <template>...</template> and then use templatizer to append the content of the template multiple times. This is for example how <template is="dom-repeat"> or <iron-list> are doing it
I'm trying to hook core-animated-pages with paper-tabs in my polymer appliaction. Everyghing looks cool , but I have trouble with changing core-animated-pages when I click on paper-tabs button
I'm trying to use This polymer tutorial , my version is very similar to tutorial so it should work. Unfortunately I can see only first core-page active or my URL is changing for http://myapp/#one or #two
My code below:
<template id="templ" is="auto-binding">
<div layout horizontal flex>
<paper-tabs id="tabs" valueattr="hash" selected="all" class="progress-tabs" self-end>
<template repeat="{{page in pages}}">
<paper-tab>{{page.name}}</paper-tab>
</template>
</paper-tabs>
</div>
<div layout horizontal center-center fit>
<core-animated-pages valueattr="hash" selected="{{hash}}"
transitions="slide-from-right">
<template repeat="{{page in pages}}">
<section hash="{{page.hash}}" layout vertical center-center>
<div>{{page.name}}</div>
</section>
</template>
</core-animated-pages>
</div>
</template>
And script:
<script>
Polymer('progress-page', {
ready: function () {
var template = this.shadowRoot.getElementById("templ");
template.pages = [
{name: 'Single', hash: 'one'},
{name: 'page', hash: 'two'}
];
}}
);
</script>
In the paper-tabs use 'selected' attribute to get the 'hash' value of selected tab:
<paper-tabs id="tabs" valueattr="hash" selected="{{selected}}" class="progress-tabs" self-end>
Then us {{selected}} value to switch the core-pages:
<core-animated-pages valueattr="hash" selected="{{selected}}"
transitions="slide-from-right">
So, 'selected' attribute passes the value between tabs and pages.
I am very new to web development and am attempting to learn to use polymer to create a simple webpage. I have created a drop down menu populated by the names in a json file similar to the below example. I cannot understand how to display the data associated with the selected menu item. below is the demo code from the polymer project. I understand this question may seem very simple to some of you. Thank you in advance for your patience and any assistance that may be provided.
<paper-menu-button>
<paper-icon-button icon="menu" noink></paper-icon-button>
<paper-dropdown class="dropdown">
<core-menu class="menu">
<template repeat="{{name in food}}">
<paper-item>{{}}</paper-item>
</template>
</core-menu>
</paper-dropdown>
</paper-menu-button>
there are several ways you can check a menu for user input.
method 1
you can use a EventListener to look for the core-select event. to do that you would give the core-menu a id. i am calling it select.
that would make the function look like
this.$.select.addEventListener('core-select', function () {
// access the value with this.selected
});
method 2
you could also use the declarative approach also using a EventListener but this time as a attribute on-core-select="{{selectAction}}" then the function would look like.
selectAction: function () {
// value would be this.$.select.selected if using the select id on the core-menu
}
method 3
you could also use a attribute changed function to get the value when changed. that method would look like.
<paper-menu-button>
<paper-icon-button icon="menu" noink></paper-icon-button>
<paper-dropdown class="dropdown">
<core-menu class="menu" selected="{{selected}}">
<template repeat="{{name in food}}">
<paper-item>{{}}</paper-item>
</template>
</core-menu>
</paper-dropdown>
</paper-menu-button>
the change would call a function that would look something like
selectedChanged: function () {
// value would be this.selected
}
i also made a plunker showing all 3 in use check console for output when selecting http://plnkr.co/edit/odQwNRLFTzyATodQUNh0?p=preview
edit: all this is assuming you are working inside a custom element. outside a custom element method 1 would still work. method 2 and 3 would require a auto-binding template
I'm very new to Polymer too, but I got tabs working this way (i think it may apply to drop-down too):
In normal web-pages:
<body>
<template is="dom-bind" id="app">
<div class="container">
<div class="menu-area">
<paper-tabs selected="{{selected}}" on-iron-select="_onTabSelected">
<template is="dom-repeat" items="[[items]]">
<paper-tab>[[item.name]]</paper-tab>
</template>
</paper-tabs>
</div>
</div>
</template>
<script>
app._onTabSelected = function (e) {
var selectedIndex = e.srcElement.selected;
var item = this.items[selectedIndex];
document.location = item.uri;
};
app.items = [
{id: 'HOME', name: 'Home', uri: "home.html"},
{id: 'PRODUCTS', name: 'Products', uri: "products.html"},
{id: 'USERS', name: 'Users', uri: "users.html"}
];
</script>
</body>
</html>
When composing new elements:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-tabs/paper-tabs.html">
<link rel="import" href="../../bower_components/paper-tabs/paper-tab.html">
<dom-module id="app-header-menu">
<template>
<div class="container">
<div class="menu-area">
<paper-tabs selected="{{selected}}" on-iron-select="_onTabSelected">
<template is="dom-repeat" items="[[items]]"><paper-tab>[[item.name]]</paper-tab></template>
</paper-tabs>
</div>
</div>
</template>
<script>
Polymer({
is: "app-header-menu",
properties: {
items: {
type: Array,
notify: false,
readOnly: false,
value: [
{id: 'HOME', name: 'Home', uri: "home.html"},
{id: 'PRODUCTS', name: 'Products', uri: "products.html"},
{id: 'USERS', name: 'Users', uri: "users.html"}
]
}
},
_onTabSelected: function (e) {
var selectedIndex = e.srcElement.selected;
var item = this.items[selectedIndex];
document.location = item.uri;
}
});
</script>
</dom-module>