biojs / biojs3

Draft of BioJS 3: Web components
BSD 3-Clause "New" or "Revised" License
18 stars 2 forks source link

Create a basic Web Component Example #2

Open wilzbach opened 9 years ago

wilzbach commented 9 years ago

Web components as the base

Hypercubed commented 9 years ago

Here is a start... https://gist.github.com/Hypercubed/37dade46dbf5e447cc95

There are some issues using d3 in a Web Component. I'm not sure if that is your plan.

Hypercubed commented 9 years ago

BTW.. this is polymer 1.0. Most examples online are 0.5; the syntax is very different.

herkulano commented 9 years ago

I've created a draft component example here: https://github.com/herkulano/biojs3-webcomponent-example

There's more documentation on Polymer's website: https://www.polymer-project.org/1.0/docs/start/reusableelements.html

Polyserve creates a page showing the component's documentation and a demo in a nice way. The developer of the component needs to comment the code in JSDoc format.

Docs

Demo

Hypercubed commented 9 years ago

Hello @herkulano,

I have a few comments/questions. Feel free to correct me if I misunderstood something. I am new to web components.

1) As far as I can tell the way you have included the styles (using link instead of style inside the component) does not isolate them. I think that is a key feature of web components. In my example above I needed to use the awkward .content-container > ::content syntax because d3 added elements are not being name spaced by polymer (or perhaps webcomponents.js).

2) I strongly encourage an alternative to (or addition to) the url attribute. In your case this restricts usage to only tsv files. What about csv or json files? Or in my case I am loading data in my application, parsing, and feeding that to visualization components. The data may be coming from and database or rest services. In my example I am feeding the data to the component as a json string... also not ideal.

3) The way you have included dependencies seams very polyserve specific. How does this work in the wild?

Hypercubed commented 9 years ago

Yes, link tags are not scoped: http://plnkr.co/edit/1sWSIz?p=preview

I think the only reason this is working in your demo is that d3 is adding the chart to 'body', outside the component itself. In my example I found an element inside the component using this.$.chart

My example: http://plnkr.co/edit/qFMzW1?p=preview

wilzbach commented 9 years ago

Wow @herkulano - I totally love the API documentation with the iron-component-page - I guess this brings us to the separate question whether we should enforce such a style guide onto the user. It might restrict them to use only Polymer only - I have moved this discussion to #8.

2) I strongly encourage an alternative to (or addition to) the url attribute. In your case this restricts usage to only tsv files. What about csv or json files? Or in my case I am loading data in my application, parsing, and feeding that to visualization components. The data may be coming from and database or rest services. In my example I am feeding the data to the component as a json string... also not ideal.

Let's discuss this at #6: I/O parsers.

3) The way you have included dependencies seams very polyserve specific. How does this work in the wild?

I guess polyserve is needed to fix the relative paths, as Polymer has this very specific structure that it expects - so otherwise <link rel="import" href="../polymer/polymer.html"> wouldn't be resolved. Well it really depends on whether we go for ES6 modules or the Polymer way with a common structure - see #4.

herkulano commented 9 years ago

@Hypercubed

Thank you for pointing out these points they've helped to understand a bit better Polymer.

1) There was a mistake in the way i was importing the css, the proper syntax is:

<link rel="import" type="css" href="my-awesome-button.css">

I've updated your plunk and now the scope works properly: http://plnkr.co/edit/Eiq98Ybsd6jdIKq2BLMk?p=preview

Another mistake i had was using d3 to append the svg element. DOM manipulation, especially insertion has to be done with the Polymer DOM API, so it can add the proper scope, so instead of using d3 i changed it to Polymer and now it is properly scoped.

var svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
Polymer.dom(this.root).appendChild(svgEl);

https://github.com/herkulano/biojs3-webcomponent-example/blob/master/biojs-component.js#L78

More info: https://www.polymer-project.org/1.0/docs/devguide/styling.html#external-stylesheets https://www.polymer-project.org/1.0/docs/devguide/local-dom.html#dom-api

2) The url is just a string property so it can be really anything .csv, .json, whatever. It's not the data itself, the data fetching is being done by d3 in this case:

d3.tsv(this.url, type, function(error, data) {

https://github.com/herkulano/biojs3-webcomponent-example/blob/master/biojs-component.js#L87

More Info: https://www.polymer-project.org/1.0/docs/devguide/properties.html

3) The dependencies are a problem that needs more definition from the web components standards themselves. As we see in issue #4

Dependencies are being managed by bower, not polyserve. So when end-users need to use your components they should use bower to install them and developers need to keep their bower.json file updated with the proper dependencies. Not entirely happy with this solution, but it seems to be the best so far.

herkulano commented 9 years ago

@Hypercubed Another thing i forgot to mention. I'm using separate files because in this way you can easily use preprocessors and linters for both css (sass, less, etc) and javascript (babel, traceur, typescript, etc).

Hypercubed commented 9 years ago

Hi @herkulano

I'm all for separate files since I plan on using SystemJS and ideally es6.

1) Good catch. 2) Yes, I meant that the d3.tsv is dictating the file type. I imagine you can support a data attribute and a url attribute but then the component would need to guess the file type from the filename. We can discuss in #6. 3) I spent much of the last two days reading up on this... there are a lot of options but few solutions.

Great work.

herkulano commented 9 years ago

My findings on the creation of elements inside the local dom.

I've moved back to d3 for the creation of the svg element for simplicity and it still works fine, but it's not class scoped:

D3 instantiation

var svg = d3.select(this).append('svg')
<svg width="640" height="480"></svg>

Polymer instantiation

var svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
Polymer.dom(this.root).appendChild(svgEl);

var svg = d3.select('svg')
<svg class="style-scope biojs-component" width="640" height="480"></svg>

The main thing is to use ::content in the css so it targets the inner elements of the component.

https://github.com/herkulano/biojs3-webcomponent-example/blob/master/biojs-component.js#L78

herkulano commented 9 years ago

Changed the script dependency to the component, looks cleaner and easier for the end-user. Would prefer a module loader though.

Component: https://github.com/herkulano/biojs3-webcomponent-example/blob/master/biojs-component.html#L29

Implemention: https://github.com/herkulano/biojs3-webcomponent-example/blob/master/demo/index.html#L10

herkulano commented 9 years ago

Using ES6 with babel

Added a branch with an ES6 test: https://github.com/herkulano/biojs3-webcomponent-example/tree/es6-test

The component works fine, but all the documentation goodness is lost.

The Polymer team is using this library: https://github.com/Polymer/hydrolysis/ to retrieve the documentation from the code, but with the transpiler the code is no longer consistent with the way they look for the documentation.

wilzbach commented 9 years ago

Amazing work @herkulano !!

The component works fine, but all the documentation goodness is lost.

The Polymer team is using this library: https://github.com/Polymer/hydrolysis/ to retrieve the documentation from the code, but with the transpiler the code is no longer consistent with the way they look for the documentation.

Oh that is pretty bad, because if I understand that correctly we have now to find a different way for the authors to annotate their components, because - even if we fix the ES6 setup - there are other libraries out there that allow to create WebComponents and it is also possible to use VanillaJS .

I could imagine that the component provides has to provide a meta file with proper annotations, in this way developer can choose between a supported library like Polymer where we can easily deduce this meta information and figuring out their own way as long as they somehow generate this common annotation file - they could even maintain it manually. Do you feel that this could be a way to go?

herkulano commented 9 years ago

@greenify

That's a great idea! In that way, we decouple the annotations from the code and developers can use whatever flavour they like. #8

A good example of this is Definition Files for TypeScript. They are completely separate from the code and you can even have other people documenting older code.

The community of TypeScript has been building definition files on their own in DefinitelyTyped

Here is the JQuery .d.ts file as an example: https://github.com/borisyankov/DefinitelyTyped/blob/master/jquery/jquery.d.ts

The only thing is that we have to write our own documentation generator or pick one that suits our needs, here's a few from a quick google search:

wilzbach commented 9 years ago

@herkulano wow! That is exactly what I imagined - I didn't know about these cool TypeScript definition files :) -> I have created #9 to track the progress of it.