How to use javascript from Dart inside a polymer element - javascript

I am trying to modify sample-google-maps to work inside a polymer element. On running following code I don't see anything except the title and there are no errors.Please advise how can I make this work.
In longer run I want to define additional components using google-chart api and Polymer dart. Can someone point me to a worked out example.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DEMO</title>
<script type="text/javascript" src="packages/web_components/platform.js"></script>
<link rel="import" href="lib_elements/googlemapcanvas/googlemapcanvas.html">
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?sensor=false">
</script>
</head>
<body>
<h1> Trial for Charted Library</h1>
<google-map-canvas></google-map-canvas>
<!-- bootstrap polymer -->
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
<script src="packages/browser/interop.js"></script>
</body>
</html>
googlemapcanvas.html
<!-- import polymer-element's definition -->
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="google-map-canvas" attributes="title">
<template>
<style>
#google-map-canvas {
height:100%
}
</style>
<h1>{{title}}</h1>
<div id="google-map-canvas"></div>
</template>
<script type="application/dart" src="googlemapcanvas.dart"></script>
</polymer-element>
googlemapcanvas.dart
import 'package:polymer/polymer.dart';
import 'dart:js' as js;
import 'dart:html';
/**
* A Polymer click counter element.
*/
#CustomTag('google-map-canvas')
class GoogleMapCanvas extends PolymerElement{
#published String title = "Google Map Canvas";
DivElement googlemapcanvas;
GoogleMapCanvas.created(): super.created(){
}
#override
void attached(){
googlemapcanvas = $['google-map-canvas'];
draw();
}
draw(){
final google_maps = js.context['google']['maps'];
var center = new js.JsObject(google_maps['LatLng'], [-34.397, 150.644]);
var mapTypeId = google_maps['MapTypeId']['ROADMAP'];
var mapOptions = new js.JsObject.jsify({
"center": center,
"zoom": 8,
"mapTypeId": mapTypeId
});
new js.JsObject(google_maps['Map'],[googlemapcanvas, mapOptions]);
}
}

This is a CSS problem, maybe specific to Polymer, but a CSS problem all the same. There are several things you can do. The simplest one is to add fullbleed as an attribute to <body>.
<body unresolved fullbleed>
</body>
And your map will show up, taking up the rest of the space available. Or you can specify the height of your google-map-canvas element to have a height in pixels like so
<polymer-element ...>
<template>
<style>
:host {
height: 500px;
}
...
</style>
...
</template>
</polymer-element>
And the map will fill the space left after the title you put just before it. But it will not go beyond the 500px that you gave the element. There are other tricks you could do. I'd look at this site for more ways to layout polymer elements
https://www.polymer-project.org/docs/polymer/layout-attrs.html
And a guide to style polymer elements
https://www.polymer-project.org/docs/polymer/styling.html
Hope that answers your questions.
By the way, you do know the is a port of Google maps API to Dart?
https://pub.dartlang.org/packages/google_maps

Related

How to use html-gl library ? Its very lack of documentation

Does anyone know how to use html-gl library ?
I tried to implement rendering HTML/CSS via WebGL. I've tried to do some WebGL postprocessing, but it started to get really slow once I created a lot of Text Geometry. I did all that with react-three-fiber framework. So I tried another alternative to achieve what I want, I tried CSS Custom Filter, but unfortunately it doesn't work yet in modern browser. And then I found html-gl library. It was really hard for me to implement that because it has a very minimal docs.
Problems:
1. I've tried to use html-gl in my project, but nothing seems to be working
2. There is also one more issue, if I click the box, the css coloring doesn't work, but if I don't wrap it with <html-gl> tag, it works as it should
here is the codesandbox:
https://codesandbox.io/s/html-gl-project-lhk2fp
Dependencies:
npm i html-gl
npm i pixi.js
Here is my code:
main.js
import './style.css';
import * as PIXI from 'pixi.js';
const redbox = document.querySelector('.box');
redbox.addEventListener('click', () => {
redbox.classList.toggle('blue');
});
// get html gl element
const htmlgl = document.getElementsByTagName('html-gl')[0];
// set up pixi stage
const stage = new PIXI.Container();
// set up renderer
const renderer = window.HTMLGL.renderer;
const displaceContainer = htmlgl.sprite; // --> this line is undefined
// displacement filter
const displacementTexture = PIXI.Texture.from('images/blur.JPG');
const displacementFilter = new PIXI.DisplacementFilter(displacementTexture);
displacementFilter.scale.x = 50;
displacementFilter.scale.y = 50;
displaceContainer.filters = displacementFilter; // --> error here
// render loop
function animate() {
renderer.render(stage);
requestAnimationFrame(animate);
}
renderer.render(stage);
requestAnimationFrame(animate);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<!-- this is the html-gl DOM -->
<html-gl>
<div id="app">
<div class="layout-flex">
<div class="box red">click me !</div>
</div>
</div>
</html-gl>
<!-- this is the html-gl DOM -->
<script
src="https://cdnjs.cloudflare.com/ajax/libs/html-gl/0.3.1/htmlgl.min.js"
integrity="sha512-MffjPWwAY9ra9a7OXYEo1j9JiYD8IHJ6Pr1hjxSKk7gNzpYk6YRFB0QOQNg7EvxBosNclFOjl7Fe+1cMGI3rEA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script type="module" src="/main.js"></script>
</body>
</html>
Any idea what goes wrong here?

External font does not load when link is loaded from inside the shadowDOM

At the begining I want to say that I'm aware that the question is similar to:
How to let imported css font / icons have effects on elements in the shadow dom?
It's not the case and it does not help.
Issue:
I've recently decided to use the ShadowDOM to encapsulate the styles in my project. At the very begining it I thought it worked as expected but I've noticed that some of the icons coming from the external CSS files were gone.
It's important to notice that those styles are external and possibilities of making changes are limited.
I've prepared the code to demonstrate the issue (look at the snippet below).
Everything seems to be working fine except the #font-face
As You can see, HTML containing the external CSS file with icons works as expected outside the ShadowDOM. I'd like to use it inside the shadowDOM as well.
How can I achieve that ?
NOTE: If you check the dev tools, there is a problem with the CSS path in network tab but it's the SO snippet issue. If You run the snippet locally, everything is ok in network.
const body = document.getElementsByTagName('body')[0];
const wrapper = document.querySelector('.wrapper')
const handleAddToShadowClick = (param) => {
const host = document.querySelector('#shadowHost');
if(param === 'insideShadow') {
const shadowRoot = host.attachShadow({mode: 'open'});
shadowRoot.innerHTML = firstComponent
} else {
const shadowRoot = host;
wrapper !== null ? body.removeChild(wrapper): ''
shadowRoot.innerHTML = firstComponent
}
}
const firstComponent = `
<div class="wrapper">
<div class="icon login">Bla bla</div>
<div style="font-family: testFont;">Sample String od text</div>
<link rel="stylesheet" href="./style.css" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css" integrity="sha384-Bfad6CLCknfcloXFOyFnlgtENryhrpZCe29RTifKEixXQZ38WheV+i/6YWSzkz3V" crossorigin="anonymous">
</div>
`
.wrapper {
font-family: agGridBalham;
background-color: aquamarine;
color: black;
}
.balham:before {
content: "\F11F";
}
.login::before {
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f007";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
Refresh the page after each button click
</p>
<button onclick="handleAddToShadowClick('outside')">Add outside shadow</button>
<button onclick="handleAddToShadowClick('insideShadow')">Add inside shadow</button>
<div>
<div id="shadowHost"> </div>
</div>
<script src="./script.js"></script>
</body>
</html>
The behavior mentioned in the question is a bug which has been there in chromium(It was also there in Gecko too not sure if it has been fixed or not).
Here is the link for the bug reported at chromium related
to this issue, which still not resolved by them. At, present i feel
this is the only workaround which will work.
The issue is mainly related to scoping of #font-face. Currently you cannot use the fonts awesome fonts when they are only included inside the shadow DOM. So inorder to use the fonts the fonts css must be present inside both light DOM and shadow DOM. So you need to import the font css both inside the shadow dom and the light dom.
Here is a Working Plunker which solves your problem.
<html>
<head>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css" integrity="sha384-Bfad6CLCknfcloXFOyFnlgtENryhrpZCe29RTifKEixXQZ38WheV+i/6YWSzkz3V" crossorigin="anonymous">
</head>
<body>
Refresh the page after each button click
</p>
<button onclick="handleAddToShadowClick('outside')">Add outside shadow</button>
<button onclick="handleAddToShadowClick('insideShadow')">Add inside shadow</button>
<div>
<div id="shadowHost"> </div>
</div>
<script src="lib/script.js"></script>
</body>
</html>
As you can see the plunker above, we have included the font-awesome css both in light DOM and Shadow Dom. And it is working fine as intended.

Order of javascript execution when loading html import

This http://webcomponents.org/polyfills/html-imports/ says following:
Under native imports, <script> tags in the main document block the loading of imports.
why then this:
<html>
<head>
<script>
console.log('index');
</script>
<script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="some-elt.html">
</head>
<body>
</body>
</html>
and some-elt.html:
<html>
<head>
<script>
console.log('import');
</script>
</head>
<html>
produces in chrome (native imports):
import
index
and in fireforx (polyfill):
index
import
?
It looks like <script> tags are blocked while imports are being loaded.
Is there also some way to ensure js execution before loading any imports?
I have created a quick pen here with markup you supplied.
It seems to be producing identical and correct output(index then import)for me in both FF and chrome.
But it is equally possible that you might be seeing something different in your console. Culprit here is not how the way script element is parsed,but rather console APIs. It is a non standard feature and might be returning different results for you as explained here
console.log is not standardized, so the behavior is rather undefined,
and can be changed easily from release to release of the developer
tools
To answer your question, script tag by design is blocking therefore any script which you put before your link rel="import" will be executed before browser encounters import tag.
Here is another pen(http://codepen.io/vishwaabhinav/pen/bEYwaK) to prove this(Also available below), where I am creating and appending divs to body in both imported and main document. It also works as expected i.e. index node is appended to body before import node.
<html>
<head>
<script>
var node = document.createElement('div');
node.innerHTML = 'Index';
document.body.appendChild(node);
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.20/webcomponents-lite.js"></script>
<link rel="import" href="http://codepen.io/vishwaabhinav/pen/XXzjZW.html">
</head>
<body>
</body>
</html>
sorry everybody, it appears to be someting wrong with build scripts. The resulting html output is as following:
<!DOCTYPE html><html><head>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.20/webcomponents-lite.js"></script>-->
<link rel="import" href="some-elt.html">
</head>
<body>
<script src="index.js"></script></body></html>
https://github.com/PolymerElements/polymer-starter-kit/issues/669

How can I pass attribute to an imported hidden custom polymer element

Before I created my custom Polymer element :
<polymer-element name="my-custom-element" attributes="key" hidden>
<script>
Polymer({});
</script>
</polymer-element>
I would like to pass an attribute to my imported hidden custom Polymer element when I import it on an other custom Polymer element like this :
<link rel="import" href="../my-custom-element/my-custom-element.html" key="15">
How could I do ? It is possible to do this ? If not what is the good way ?
As wirlez pointed out, you'll want to import your element's definition, create an instance, and set the key value as an attribute.
For example:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Polymer</title>
<script src="http://www.polymer-project.org/components/webcomponentsjs/webcomponents.js"></script>
<!-- import element definition from jsbin -->
<link rel="import" href="http://jsbin.com/mojadu.html">
</head>
<body>
<x-foo key="42"></x-foo>
</body>
</html>
element definition
<!-- Make sure your element imports Polymer as a dependency -->
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<polymer-element name="x-foo" attributes="key" hidden>
<template>
<h1>Hello from x-foo</h1>
<h2>The key is {{key}}</h2>
</template>
<script>
Polymer({
keyChanged: function(oldVal, newVal) {
console.log('the key is', newVal);
}
});
</script>
</polymer-element>
Here's the example running in jsbin.
If you look in the console, you'll see the element is logging the value for key.
If you're trying to access the element using JavaScript in index.html you may need to wait for the polymer-ready event before manipulating it.
ex:
document.addEventListener('polymer-ready', function() {
var el = document.querySelector('x-foo');
// do something with x-foo that involves its key
});
To pass a custom attribute you need a custom element. The tag "link" is no custom element. To create your own custom-elements and implement them to your web-application read this.
If you haven't already, follow the whole tutorial :)
Edit:
An import of a custom element is not the same as using it. What you can do it that you import your custom element then write the tag with specific attributes.
<my-custom-element key="15"></my-custom-element>
Much like core-ajax is used:
<core-ajax
auto
url="http://gdata.youtube.com/feeds/api/videos/"
params='{"alt":"json", "q":"chrome"}'
handleAs="json"
on-core-response="{{handleResponse}}"></core-ajax>
It seems like you want to have it like this:
<link
rel="import"
href="../core-ajax/my-custom-element.html"
auto
url="http://gdata.youtube.com/feeds/api/videos/"
params='{"alt":"json", "q":"chrome"}'
handleAs="json"
on-core-response="{{handleResponse}}"></link>
Sorry that is not how Polymer works!
lets say this is you polymer file:
<polymer-element name="my-custom-element" attributes="key" hidden>
<script>
Polymer({});
</script>
</polymer-element>
and this is your link importing the file in your html:
<link rel="import" href="../my-custom-element/my-custom-element.html" key="15">
there's a couple of ways to do what you ask...
if you wish to create that value dynamically then the best way is to create a constructor for the custom element like this:
<polymer-element name="my-custom-element" constructor='MyCustomElement' attributes="key" hidden>
<script>
Polymer({});
</script>
</polymer-element>
then create an instance of such element on the code of the polymer element, something like:
var custom = new MyCustomElement();
place that element into your DOM like:
var dom = document.querySelector('otherElement'); //depending on scope
dom.appendChild(custom);
custom.setAttribute('atribute', value);
or
this.$.elementID.appendChild(custom);
custom.setAttribute('atribute', value);
I hope this is somewhat what you're looking for. cheers

Date Input Field with Polymer?

Has anyone got any recommendations for a date input element with Polymer. Something more user friendly than a number of combobox's
The Polymer-Date-Picker project seems to have an issue with multiple input fields on the same page (which I have reported)
A possible starting point is wrapping an existing date-input field library within a Polymer element.
Here's a Live Demo wrapping Pikaday, a lightweight and configurable JavaScript datepicker, within a custom Polymer element.
Note the comments within the example's source code.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://www.polymer-project.org/platform.js"></script>
<!-- HTML import of the custom `pikaday-element` -->
<link rel="import" href="pikaday-element.html">
</head>
<body>
<pikaday-element></pikaday-element>
</body>
</html>
<!-- pikaday-element.html -->
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<polymer-element name="pikaday-element">
<template>
<link rel="stylesheet" href="https://rawgit.com/dbushell/Pikaday/master/css/pikaday.css">
<input type="text" id="datepicker">
<div id="container"></div>
</template>
<script src="https://rawgit.com/dbushell/Pikaday/master/pikaday.js"></script>
<script>
Polymer({
ready: function() {
var picker = new Pikaday({
// targets the #datepicker id within the shadow DOM.
field: this.$.datepicker,
// targets the #container id within the shadow DOM.
container: this.$.container,
// automatically show the datepicker on-load.
// note: when set to true, it flashes for a brief moment and then hides
bound: false
});
}
});
</script>
</polymer-element>
Since this is just a starting point, you can just configure the datepickers and settings as you see fit.
Big thanks to the Ampersand JS Toolkit for introducing me to Pikaday and to RawGit for hosting Pikaday assets.
Cheers!

Categories