[Dart+Polymer] Styling Elements

Styling custom elements is sometimes tricky. In general the website styles do NOT apply to the custom element. There is a special attribute called “apply-author-styles” that can be set to “true” to apply your website’s styles to your custom element.

In general each custom element should have its  styles separated from the website so it can be reused easily. Let’s have a look at a simple example:

dart_polymer_styling.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Dart polymer styling</title>
    <link rel="import" href="external-styles.html">
    <link rel="import" href="internal-styles.html">
    <style>
      .styled {
        background-color: yellow;
        font-weight: bold;
        font-style: italic;
      }
    </style>
  </head>
  <body>
    <external-styles></external-styles>
    <internal-styles></internal-styles>

    <script type="application/dart" src="dart_polymer_styling.dart"></script>
    <script src="packages/browser/dart.js"></script>
  </body>
</html>

This simple HTML file imports two custom elements from two separate files and defines a small CSS rule.

dart_polymer_styling.dart

import 'package:polymer/polymer.dart';

void main() {
  initPolymer();
}

The corresponding .dart-file is rather small and could be avoided if the init script from polymer is used directly

The two custom elements look like this:

external-styles.dart

<polymer-element name="external-styles">
  <template>
    <div class="styled">Externally Styled</div>
  </template>
  <script type="application/dart" src="external-styles.dart"></script>
</polymer-element>

external-styles.html

import 'package:polymer/polymer.dart';

@CustomTag('external-styles')
class ExternalStylesElement extends PolymerElement {
  bool get applyAuthorStyles =&gt; true;

  ExternalStylesElement.created() : super.created() {
    print(this.toString() + " created");
  }
}

internal-styles.dart

<polymer-element name="internal-styles">
  <template>
    <style>
      .styled {
        color: #f00;
      }
    </style>
    <div class="styled">Internally Styles</div>
  </template>
  <script type="application/dart" src="internal-styles.dart"></script>
</polymer-element>

internal-styles.html

import 'package:polymer/polymer.dart';

@CustomTag('internal-styles')
class InternalStylesElement extends PolymerElement {
  // applyAuthorStyles is false by default

  InternalStylesElement.created() : super.created() {
    print(this.toString() + " created");
  }
}

As you can see here the trick with polymer elements in Dart is to define/overwrite the getter for applyAuthorStyles. Also make sure the <style>-tag is inside of your <template>-tag.

Animatr – GUI & Structure: Nesting Polymer Elements

The first step of rebuilding animatr was to remove all code and totally rebuild the GUI using a single custom element: <animatr-gui> using polymer. The GUI itself has three nested custom elements:

<animatr-titlebar> - Containins the windows’ title, close button, …
<animatr-toolbars> – Wrapper for the toolbars
<animatr-panels> – A wrapper to create a GUI using pannels that can be dragged.

The HTML code of the root element looks like this:

<head>
  <link href="packages/animatr_gui/elements/animatr-ui.html" rel="import" />
</head>
<body>
  <animatr-ui></animatr-ui>
</body>

The corresponding element HTML code is:

<polymer-element name="animatr-ui">
  <meta charset="utf-8"/>
  <link rel="import" href="animatr-titlebar.html">
  <link rel="import" href="animatr-toolbars.html">
  <link rel="import" href="animatr-panels.html">
  <link rel="import" href="animatr-panel-....html">
  <template>
      <animatr-titlebar id="animatr-titlebar"></animatr-titlebar>
      <animatr-toolbars id="animatr-toolbars"></animatr-toolbars>
      <animatr-panels id="animatr-panels"></animatr-panels>
  </template>
  <script type="application/dart" src="animatr-ui.dart"></script>
</polymer-element>
 

The Dart code for the custom element is:


import 'package:polymer/polymer.dart';

import 'dart:html';

import 'package:animatr_gui/elements/animatr-titlebar.dart';
import 'package:animatr_gui/elements/animatr-toolbars.dart';
import 'package:animatr_gui/elements/animatr-panels.dart';

import 'animatr-panel-....dart';

@CustomTag('animatr-ui')
class AnimatrUiElement extends PolymerElement {
  bool get applyAuthorStyles =&gt; true;

  ...PanelElement panel_...;

  AnimatrUiElement.created() : super.created() {
    panel_... = document.createElement('animatr-panel-...');
  }

  AnimatrTitlebarElement titlebar;

  AnimatrToolbarsElement toolbars;

  AnimatrPanelsElement panels;

  @observable Project currentProject;

  @override
  void enteredView() {
    super.enteredView();

    titlebar = $['animatr-titlebar'];
    toolbars = $['animatr-toolbars'];
    panels = $['animatr-panels'];

    titlebar.ui = this;
    panels.ui = this;

    panels.addPanel(panel_..., 'north/east/south/west/center');
   }
}

Nesting elements was complicated first. Assuming you have your project’s root file (mine is called animatr.html), you could import all elements in this file, at a central place. But this had some strange behaviour to me:
The outer elements get created first and thus, before all nested elements. Thus I wasn’t able to correctly query for the nested elements. Because the custom element wasn’t registered Google Dart had some type errors.

The solution was to import other elements within the custom element itself, right before the <template> tag.

I had another problem using special characters. It turned out that the charset settings (e.g. by using <meta charset=”utf-8″/>) is not propagated to custom elements. Thus make sure to include a <meta>-tag in your custom elements if you want to use custom elements.

Animatr – A first introduction

In this post I want to briefly introduce you to my most recent project called “animatr”. Animatr is a tool to create canvas animations. I will focus on advertisements but in theory you can create all types of animations and sizes. Even playing a video within the animation is possible.

The first version was developed about a year ago and was based on fabric.js But very soon I felt the framework limited me to their features. So I quickly decided to rewrite it as a web app on my own. Due to some specific webkit/chrome features I decided to finally rewrite the project using Google’s Dart and to make an app out of it using node-webkit.

The latest and third version is based on Google Dart, Node-Webkit and Polymer. While polymer is the replacement for web-ui.

I will write follow up blogs about concepts and code I use while developing animatr and give you examples. So far I can tell that detailed examples are rare. That’s why I felt to blog about it myself.

My blog

I have been thinking for years now if I should start blogging or not. Finally I decided to do so :)

I will be blogging about all web topics I will deal with. Nevertheless I want to focus on Dart + Polymer I have been working on recently.