Dart: a New Web Programming Experience

Once the onResponse() callback is executed, I pull the InputStream object out of the response to begin reading data. I register the onData(), onClosed() and onError() callbacks to handle the different states the InputStream can be in. onData() simply reads bytes off the stream and appends them to the jsonData list object. onData() is guaranteed to be called as long as there is data to read. Once the stream has hit "end of file", onClosed() is executed. At this point, I know all of the data from the HttpRequest has been transferred and read, so I can use the JSON helper class to parse the response into a Map object and print the final result to the user. This is where the program actually exits from if everything was successful. If there was an error in the InputStream, then the onError() callback would have been called, and the program would have exited from there.

To run this program, call it with the Dart runtime environment. You will need to register for an API key from Weather Underground (http://www.wunderground.com/weather/api). Don't worry; it's completely free. Once you have your API key, you can check the current temperature for any US zip code:


$ dart wunder.dart ec7....93b 10001
The temperature for New York, NY is 57.2 F (14.0 C)

Client-Side Dart

Now that you've seen what Dart can do on the server side, let's take a look at what it really was designed for, the client side. Dart excels at programming large-scale browser applications. Unfortunately, space constraints prevent me from showing a truly large application. Instead, I cover a not-so-large but very cool application using the HTML5 Canvas object. Let's use Dart for finger painting.

Listing 2. fingerpaint.dart


library fingerpaint;

import 'dart:html';

class DrawSurface {
  String _color = "black";
  int _lineThickness = 1;
  CanvasElement _canvas;
  bool _drawing = false;
  var _context;
  
  DrawSurface(CanvasElement canvas) {
    _canvas = canvas;
    _context = _canvas.context2d;
    _canvas.on.mouseDown.add((Event e) => _onMouseDown(e));
    _canvas.on.mouseUp.add((Event e) => _onMouseUp(e));
    _canvas.on.mouseMove.add((Event e) => _onMouseMove(e));
    _canvas.on.mouseOut.add((Event e) => _onMouseUp(e));
  }

  set lineThickness(int lineThickness) {
    _lineThickness = lineThickness;
    _context.lineWidth = _lineThickness;
  }

  set color(String color) {
    _color = color;
    _context.fillStyle = _color;
    _context.strokeStyle = _color;
  }

  int get lineThickness => _lineThickness;

  int get color => _color;
  
  void incrementLineThickness(int amount){
    _lineThickness += amount;
    _context.lineWidth = _lineThickness;
  }

  String getPNGImageUrl() {
    return _canvas.toDataUrl('image/png');
  }

  _onMouseDown(Event e){
    _context.beginPath();
    _context.moveTo(e.offsetX, e.offsetY);
    _drawing = true;
  }

  _onMouseUp(Event e){
    _context.closePath();
    _drawing = false;
  }

  _onMouseMove(Event e){
    if (_drawing == true){
      _drawOnCanvas(e.offsetX, e.offsetY);
    }
  }

  _drawOnCanvas(int x, int y){
    _context.lineTo(x, y);
    _context.stroke();
  }

}

void main() {
  CanvasElement canvas = query("#draw-surface");
  DrawSurface ds = new DrawSurface(canvas);
  
  List<Element> buttons = queryAll("#colors input");
  for (Element e in buttons){
    e.on.click.add((Event eve) {
      ds.color = e.id;
    });
  }

  var sizeDisplay = query("#currentsize");
  sizeDisplay.text = ds.lineThickness.toString();

  query("#sizeup").on.click.add((Event e) {
    ds.incrementLineThickness(1);
    sizeDisplay.text = ds.lineThickness.toString();
  });

  query("#sizedown").on.click.add((Event e) {
    ds.incrementLineThickness(-1);
    sizeDisplay.text = ds.lineThickness.toString();
  });

  query("#save").on.click.add((Event e) {
    String url = ds.getPNGImageUrl();
    window.open(url, "save");
  });
}

Listing 3. fingerpaint.html


<!DOCTYPE html>
<html>
   <head>
      <h3>Finger Paint</h3>
      <link rel="stylesheet" href="fingerpaint.css" />
   </head>
   <body>
      <h1>Finger Paint</h1>
      <div>
         <canvas id="draw-surface" width="800px" height="600px">
         </canvas>
      </div>
      <div id="colors">
         <input id="white" type="button"></input>
         <input id="red" type="button"></input>
         <input id="black" type="button"></input>
         <input id="blue" type="button"></input>
         <input id="green" type="button"></input>
         <input id="purple" type="button"></input>
         <input id="yellow" type="button"></input>
         <input id="orange" type="button"></input>
         <input id="brown" type="button"></input>
      </div>
      <div>
         <input id="sizeup" type="button" value="Increase width">
         </input>
         <input id="sizedown" type="button" value="Decrease width">
         </input>
         <span id="currentsize"></span>
      </div>
      <div>
         <input id="save" type="button" value="Save"></input>
      </div>
      <script type="application/dart" src="fingerpaint.dart">
      </script> 
      <script type="application/javascript"
         src="http://dart.googlecode.com/svn/trunk/dart/client/dart.js">
      </script>
   </body>
</html>

Listing 4. fingerpaint.css


#draw-surface {
   border-style: solid;
   border-width: 2px;
}
#white {
   background-color: white;
   width: 30px;
}
#red {
   background-color: red;
   width: 30px;
}
#black {
   background-color: black;
   width: 30px;
}
#blue {
   background-color: blue;
   width: 30px;
}
#green {
   background-color: green;
   width: 30px;
}
#purple {
   background-color: purple;
   width: 30px;
}
#yellow {
   background-color: yellow;
   width: 30px;
}
#orange {
   background-color: orange;
   width: 30px;
}
#brown {
   background-color: brown;
   width: 30px;
}

In our simple finger-painting application, there will be buttons for each color that is available to users, as well as buttons to increment and decrement the thickness of their strokes. What good is painting a masterpiece if you can't save it and share it with the world? So, let's make a save button that will convert the canvas to a PNG image.

First, let's take a look at the markup for this project. In Listing 3, you can see there is an HTML5 Web page that contains a canvas element called draw-surface. This is where the work of art will be made. Below the canvas are the control buttons that allow users to select colors and stroke width, and the save button. The last part of the document is the most interesting part. There are two script elements. The first is a script tag with the type attribute set to "application/dart". This script type is currently recognized only by a fork of Chromium called Dartium (http://www.dartlang.org/dartium). The second is a JavaScript bootstrap file that is required to start the Dart VM in Dartium. It also has a special second function that I talk about later.

Now let's take a look at the application itself. At the top of Listing 2, I start the program by importing dart:html. All client-side applications must import this library to have access to the DOM. Next, I create a class called DrawSurface that will act as a container class for the canvas object. The constructor takes in a CanvasElement and grabs its 2-D-rendering context. It also registers all of the callbacks to handle mouse movements on the draw surface. When the user presses down on the mouse, somewhere on the draw surface canvas I begin a draw path.

As the user moves the mouse around with the button pressed down, I add line segments to the drawing. When the user releases the mouse or moves out of the canvas element, I close the drawing path.

I implemented getters and setters for the color and lineThickness attributes. In the setter methods, I make sure to update the rendering context on any change. I also add two methods incrementLineThickness(int amount) that will allow the user to adjust the lineThickness by some amount, instead of just setting it, and getPNGImageUrl() to expose the canvas element's toDataUrl() method. This method will allow the save button to function.

In main, I use the static query(String selector) function to get the canvas element by its ID. The query function takes any CSS selector and returns an Element object that matches it. If there is more than one element that you want to access on a page, you can use the queryAll(String selector) function that will return a List<Element> object. I use this function to gather up all of the color buttons at once and register onClick() events to set the current color to its respective ID value.

Finally, I register the callbacks for the size-up and size-down buttons that change the thickness of the line by 1. I also register the callback for the save button to grab the PNG data URL from the canvas and open it in a new window. The user then can save the image by right-clicking on it and choosing "save image as".

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

This is really useful

lisaedward123's picture

This is really useful information. Thanks for sharing this article.
Java training in chennai

Android mobile development in chennai

android mobile development in chennai's picture

android mobile development in Chennai

Excellent in your post in all process you can explain in line by line clearly it is one one of the new way of thinking.

Panda SEO

jamesagrata's picture

High quality written content along with inbound links performed a essential component throughout ranking assessment and yes it seems Yahoo and google will do identical show up although initial let’s go through the different character which will render SEARCH ENGINE OPTIMISATION. pandalinkbuilders

This is really nice. Thanks

lisaedward's picture

This is really nice. Thanks for your information.
java training institute in Chennai

Reply to comment | Linux Journal

skip hire adelaide's picture

A work mate referred me to your site. Thanks for the details.

キネティックは自動巻き時計と同様にローターを内蔵し、腕の振

laulan's picture

キネティックは自動巻き時計と同様にローターを内蔵し、腕の振りによって発電を行う電池交換不要のクォーツ腕時計である。装着していない時には省電力のため針の動きが自動的に停止し、再び装着され振動が与えられるとそれをバーバリー腕時計感知して自動的に現在時刻に復帰するオートリレー機能を組み込んだ「キネティックオートリレー」、小の月だけでなくうるう年においても正しい日付を示すパーペチュアルカレンダーの「キネティックパーペチュアル」、手巻き充電にも対応し、パワーリザーブ表示機能を持つ「キネティック・ダイレクトドライブ」もある。

キネティックは自動巻き時計と同様にローターを内蔵し、腕の振

laulan's picture

キネティックは自動巻き時計と同様にローターを内蔵し、腕の振りによって発電を行う電池交換不要のクォーツ腕時計である。装着していない時には省電力のため針の動きが自動的に停止し、再び装着され振動が与えられるとそれをバーバリー腕時計感知して自動的に現在時刻に復帰するオートリレー機能を組み込んだ「キネティックオートリレー」、小の月だけでなくうるう年においても正しい日付を示すパーペチュアルカレンダーの「キネティックパーペチュアル」、手巻き充電にも対応し、パワーリザーブ表示機能を持つ「キネティック・ダイレクトドライブ」もある。

good & informative article

Anonymous's picture

I prefer CoffeeScript but after seeing the feature/function integration Dart represents, I've decided to give it a second look.

The more I use it the more I like the "batteries included" approach of the Dart project: Dart Editor, Dart VM, dart2js, pub (package manager), etc.

thanks for a very informative article re subject;

This is really nice. Thanks

lisa's picture

This is really nice. Thanks for your information.
Dot net course in Chennai

Preview comment | Linux Journal

best tire deal's picture

Hi there i am kavin, its my first time to commenting anywhere, when i read
this piece of writing i thought i could
also create comment due to this brilliant piece of writing.

Yes

Clairevoyance's picture

Oui je suis d'accord et merci pour ce bon code php. Pour ma part, j'utilise un code php pour le cache du serveur. Cela me permet de booster mon site de voyance sérieuse et d'offrir gratuitement ce service de voyance gratuitement à tous mes visiteurs.

So when they found it hard to

Anis's picture

So when they found it hard to optimize Javascript some more they invented new language. Great, exactly like if college students write their own questions and answer them instead of teachers questions that are too hard to answer.

Updated examples

jslocum's picture

Things go away and things get

Marjorie Lanphear's picture

Things go away and things get backdated. JavaScript is no longer as great thing as past time. We used to invest prime time on this!

  • Quite some australian gamblers are getting unwell and tired of pubs and land based mostly on line betting site and they are normally getting the changeover to online pokies. You can find a lot of strengths to online wager site.

Very interesting topic will

zeennate's picture

Very interesting topic will bookmark your site to check if you write more about in the future.
voyance gratuite

Google is Evil

Anonymous's picture

As a computer scientist, I'm laughing. Google's Go and now Dart? Why don't you read between the lines of a $25 billion global corporation? Microsoft is a $50 billion global corporation. Today's Google == Evil news: "Google Abandons Open Standards for Instant Messaging". Yesterday, it was more evil news from Google. Wake up you clueless idiots!

Your issue of google talk is

Anonymous's picture

Your issue of google talk is a real issue:
From EFF:
https://www.eff.org/deeplinks/2013/05/google-abandons-open-standards-ins...

privacy conscious users who want to use Off-the-Record encryption where possible, but to keep messages out of their Gmail accounts in any case, are out of luck. And if they wish to continue chatting with their friends on Google chat, they can't even take their business elsewhere.

provide Google with information about the content of their messages, or even when and from where they have logged in.

Comment: the google talk change, looks to be a mandate to compily with federal rules for tracablity.

Reply to comment | Linux Journal

capsiplex news's picture

Do you have a spam issue on this site; I also am a blogger, and I was wondering your situation; we have created some nice methods and we are looking to
exchange techniques with other folks, please shoot me an email if interested.

Dart is BSD License Go is

Anonymous's picture

Dart is BSD License

Go is licensed under the Creative Commons Attribution 3.0 License, and code is licensed under a BSD license

How come as CS scientist you can not us the web to find such thing out.

Oh ya, your a troll, lol

Cloud apps NEED Dart

Jim Birch's picture

AFAICS the push to sophisticated browser-to-cloud applications will necessitate a shift from javascript. JS is great for a a bit of chunky screen animation and a bit of background I/O but I can't see that it is really up to running the big browser applications of the future. It's too messy in too many ways to develop something with a capacity like Photoshop. And this is where Google Docs etc are headed.

I'm not sure

Curtis's picture

I like it that it's a typed language unlike PHP. I question Google's motives, however.

typed language ???

Anonymous's picture

Who need TYPED language at these days, @ WEB & today's resources ?!?

This looks very cool, is Dart

Steeve McCauley's picture

This looks very cool, is Dart embedded in chrome?

Blossom switches from JavaScript to Dart

Thomas Schranz's picture

I've written an article on our decision to switch from JavaScript to Dart. You can read it here
http://www.ramen.io/post/46936028144/we-are-switching-to-dart-why

We hope better than Java

evoanuncios's picture

We hope that Dart will be better than Java..

Thanks

Dart is like Java in browser.

Anonymous's picture

Dart is like Java in browser. Awful.

Dart in the browser

tracker1's picture

Dart is much more like CoffeeScript in the browser... It is a language, and an optional runtime is cross-compile to JavaScript, which is then run in the browser. The biggest wart is that debugging becomes very cumbersome and difficult. Other than that, I don't mind that it exists. There's also TypeScript if you're wanting an extension that cross-compiles to JS. For the record, I'm fine with JS, my style of programming tends to avoid a lot of the warts.

Moving away from class-based thinking, and more about module and functional patterns and passing state objects tends to work better anyhow. YMMV of course, but I happen to like JS as-is. That said, I don't fault anyone wanting to try something new/different.

--
Michael J. Ryan - http://tracker1.info/

Good to know idiocy is

Anonymous's picture

Good to know idiocy is thriving with a comment like that.

Idiocy resorts to name

Anonymous's picture

Idiocy resorts to name calling instead of giving a legitimate critic.

how so? please

eMBee's picture

how so?
please elaborate.

greetings, eMBee.

Reply to comment | Linux Journal

http://www.tablettegraphique123.net/'s picture

Your style is really unique compared to other people I have read stuff from.
Many thanks for posting when you've got the opportunity, Guess I'll just
bookmark this page.

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix