I am new to Dart. To become familiar with Dart, I created this script. It works fine with the editor and pub serve. But pub serve dart2js logs these two warnings, which I do not understand:
No member named 'length' in class 'ElementList'
No operator '[]' in class ElementList
coloring.dart:
import 'dart:math';
import 'dart:html';
import 'dart:async';
const String CLICK_ME = 'Click me to pause!';
void randomColoring(StreamSubscription subscription) {
final Random random = new Random();
final Element intro = querySelector("#intro");
final ElementList<Element> boxes = querySelectorAll('.box');
final Element info = querySelector("#info");
subscription.onData((eventValue) {
var box = random.nextInt(boxes.length); /// WARNING
var hexCssColor = random.nextInt(0xFFFFFF + 1).toRadixString(16)
.padLeft(6, "0").toUpperCase();
boxes[box].style.background = "#$hexCssColor"; /// WARNING
info.text = eventValue.toString();
print("box: $box - hexCssColor: $hexCssColor - count: $eventValue");
});
var text = intro.text;
intro
..text = CLICK_ME
..onClick.listen((mouseEvent) {
if (subscription.isPaused) {
intro.text = CLICK_ME;
subscription.resume();
} else {
intro.text = text;
subscription.pause();
}
});
}
There is a bug for the [] operator of ElementList https://code.google.com/p/dart/issues/detail?id=19628 (fixed at June 26).
What Dart version are you using?
I wasn't able to find something about length but I guess it's a bug in Dart2JS.
You can report it at http://dartbug.com/new
But maybe the fix for the [] bug applies here as well.
Related
Let's say we want to create a simple dart file, that just declares a class containing consts. E.g.
class StringNames {
static const String helloWorld = 'Hello World';
}
But rather than write this manually, we want to generate this file programmatically. We want a program that will create this file for us.
We could write such a program in dart itself, e.g.
import 'dart:io';
void main() {
final f1 = 'file1.dart';
File(f1).writeAsString('class stringNames {\nstatic const String helloWorld = \'HelloWorld\';\n}');
}
Naturally this feels wrong. Is there a better way to achieve this?
You could use multi-line string as described here in the Dart language tour:
https://dart.dev/guides/language/language-tour#strings
So your example becomes like this, which is much more readable:
import 'dart:io';
void main() {
final f1 = 'file1.dart';
File(f1).writeAsString('''
class StringNames {
static const String helloWorld = 'Hello World';
}
''');
}
You can also use this and insert values from variables inside the string like this:
import 'dart:io';
void main() {
final f1 = 'file1.dart';
final someValue = 42;
File(f1).writeAsString('''
class StringNames {
static const String helloWorld = 'Hello World';
static const int someValue = $someValue;
}
''');
}
I have a list of models that I need to create a mini reflective system.
I analyzed the Serializable package and understood how to create one generated file per file, however, I couldn't find how can I create one file for a bulk of files.
So, how to dynamically generate one file, using source_gen, for a list of files?
Example:
Files
user.dart
category.dart
Generated:
info.dart (containg information from user.dart and category.dart)
Found out how to do it with the help of people in Gitter.
You must have one file, even if empty, to call the generator. In my example, it is lib/batch.dart.
source_gen: ^0.5.8
Here is the working code:
The tool/build.dart
import 'package:build_runner/build_runner.dart';
import 'package:raoni_global/phase.dart';
main() async {
PhaseGroup pg = new PhaseGroup()
..addPhase(batchModelablePhase(const ['lib/batch.dart']));
await build(pg,
deleteFilesByDefault: true);
}
The phase:
batchModelablePhase([Iterable<String> globs =
const ['bin/**.dart', 'web/**.dart', 'lib/**.dart']]) {
return new Phase()
..addAction(
new GeneratorBuilder(const
[const BatchGenerator()], isStandalone: true
),
new InputSet(new PackageGraph.forThisPackage().root.name, globs));
}
The generator:
import 'dart:async';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
import 'package:glob/glob.dart';
import 'package:build_runner/build_runner.dart';
class BatchGenerator extends Generator {
final String path;
const BatchGenerator({this.path: 'lib/models/*.dart'});
#override
Future<String> generate(Element element, BuildStep buildStep) async {
// this makes sure we parse one time only
if (element is! LibraryElement)
return null;
String libraryName = 'raoni_global', filePath = 'lib/src/model.dart';
String className = 'Modelable';
// find the files at the path designed
var l = buildStep.findAssets(new Glob(path));
// get the type of annotation that we will use to search classes
var resolver = await buildStep.resolver;
var assetWithAnnotationClass = new AssetId(libraryName, filePath);
var annotationLibrary = resolver.getLibrary(assetWithAnnotationClass);
var exposed = annotationLibrary.getType(className).type;
// the caller library' name
String libName = new PackageGraph.forThisPackage().root.name;
await Future.forEach(l.toList(), (AssetId aid) async {
LibraryElement lib;
try {
lib = resolver.getLibrary(aid);
} catch (e) {}
if (lib != null && Utils.isNotEmpty(lib.name)) {
// all objects within the file
lib.units.forEach((CompilationUnitElement unit) {
// only the types, not methods
unit.types.forEach((ClassElement el) {
// only the ones annotated
if (el.metadata.any((ElementAnnotation ea) =>
ea.computeConstantValue().type == exposed)) {
// use it
}
});
});
}
});
return '''
$libName
''';
}
}
It seems what you want is what this issue is about How to generate one output from many inputs (aggregate builder)?
[Günter]'s answer helped me somewhat.
Buried in that thread is another thread which links to a good example of an aggregating builder:
1https://github.com/matanlurey/build/blob/147083da9b6a6c70c46eb910a3e046239a2a0a6e/docs/writing_an_aggregate_builder.md
The gist is this:
import 'package:build/build.dart';
import 'package:glob/glob.dart';
class AggregatingBuilder implements Builder {
/// Glob of all input files
static final inputFiles = new Glob('lib/**');
#override
Map<String, List<String>> get buildExtensions {
/// '$lib$' is a synthetic input that is used to
/// force the builder to build only once.
return const {'\$lib$': const ['all_files.txt']};
}
#override
Future<void> build(BuildStep buildStep) async {
/// Do some operation on the files
final files = <String>[];
await for (final input in buildStep.findAssets(inputFiles)) {
files.add(input.path);
}
String fileContent = files.join('\n');
/// Write to the file
final outputFile = AssetId(buildStep.inputId.package,'lib/all_files.txt');
return buildStep.writeAsString(outputFile, fileContent);
}
}
So I'm getting a "Error #1063: Argument count mismatch" error. The weird thing is that it isn't keeping the game from running, but I would like to know why I'm even getting an error in the first place. The full error is:
ArgumentError: Error #1063: Argument count mismatch on Hock(). Expected 3, got 0.
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at flash.display::MovieClip()
at PlayScreen()[Z:\PROJECTS\Silversound\Occulus Squish\Oculus Squish\Classes\PlayScreen.as:30]
at Main/addPlayscreen()[Z:\PROJECTS\Silversound\Occulus Squish\Oculus Squish\Classes\Main.as:17]
at Main()[Z:\PROJECTS\Silversound\Occulus Squish\Oculus Squish\Classes\Main.as:13]
at runtime::ContentPlayer/loadInitialContent()
at runtime::ContentPlayer/playRawContent()
at runtime::ContentPlayer/playContent()
at runtime::AppRunner/run()
at ADLAppEntry/run()
at global/runtime::ADLEntry()
The Code for PlayScreen is:
import flashx.textLayout.formats.BackgroundColor;
import flash.display.SimpleButton;
import flash.ui.Mouse;
import flash.text.TextField;
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class PlayScreen extends MovieClip
{
public var batArmy:Array;
public var hockArmy:Array;
public var shadow:Shadow;
public var crossHairs:CrossHairs;
var Layer01:MovieClip;
var Layer02:MovieClip;
var Layer03:MovieClip;
var Layer04:MovieClip;
var Layer05:MovieClip;
var randomX:Number = 300 + (660 - 300) * Math.random();
public function PlayScreen()
{
//Mouse.hide();
addBatButton.addEventListener(MouseEvent.CLICK, addBat);
addHockButton.addEventListener(MouseEvent.CLICK, addHock);
batArmy = new Array();
hockArmy = new Array();
//addEventListener(Event.ENTER_FRAME, crossHairsMove);
//stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyPress );
Layer01 = new MovieClip;
this.addChild(Layer01);
Layer02 = new MovieClip;
this.addChild(Layer02);
Layer03 = new MovieClip;
this.addChild(Layer03);
Layer04 = new MovieClip;
this.addChild(Layer04);
Layer05 = new MovieClip;
this.addChild(Layer05);
//add crossHair
/*crossHairs = new CrossHairs(mouseX,mouseY,this);
Layer05.addChild (crossHairs);
addEventListener(Event.ENTER_FRAME, crossHairsMove);*/
}
/*public function onKeyPress( keyboardEvent:KeyboardEvent ):void
{
if ( keyboardEvent.keyCode == Keyboard.DOWN )
{
trace("yar");
addBat;
}
}*/
public function addBat( mouseEvent:MouseEvent ):void
{
var randomX:Number = 300 + (660 - 300) * Math.random();
var newBat = new Bat( randomX, -50, this);
batArmy.push ( newBat );
Layer02.addChild (newBat);
}
public function addHock( mouseEvent:MouseEvent ):void
{
var newHock = new Hock(-72, 170, this);
hockArmy.push ( newHock );
Layer02.addChild (newHock);
}
/*public function crossHairsMove ( e:Event ):void
{
crossHairs.x = mouseX;
crossHairs.y = mouseY;
}*/
}
and from the looks of it the error has something to do with the Hock class, so here's the code for that:
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.events.Event;
public class Hock extends MovieClip
{
private var _screen: PlayScreen;
public var xSpeed:Number;
public function Hock( startX:Number, startY:Number, screen:PlayScreen )
{
_screen = screen;
x = startX;
y = startY;
width = 100;
scaleY = scaleX;
addEventListener(Event.ENTER_FRAME, moveRightFar);
addEventListener(Event.ENTER_FRAME, moveSpeed)
}
public function moveSpeed( e:Event ):void
{
x += xSpeed;
}
public function moveRightFar ( e:Event): void
{
if (x < 0)
{
gotoAndStop("rollRight");
xSpeed = 13;
}
else if (x >= 240)
{
gotoAndStop("still")
xSpeed = 0;
}
}
}
Now I could be wrong but I think it's having a problem with var newHock = new Hock(-72, 170, this); in the "addHock" function, but I have 3 arguments there, not 0. Right? Anyway, like I said, it's not keeping the game from running but it is kind of annoying, so any insight is welcome. I'm sure it's something obvious. Thanks!
I have a guess, but I'll explain how i got there first ...
the first line of the stacktrace pointing at your source code is
at PlayScreen()[Z:\PROJECTS\Silversound\Occulus Squish\Oculus Squish\Classes\PlayScreen.as:30]
which points at the first line of the constructor of PlayScreen: addBatButton.addEventListener(MouseEvent.CLICK, addBat);
but obviously the problem is not there ...
But PlayScreen extends MovieClip and since you didn't specifically included a super() statement, the compiler will put that at as the first command. In fact, the previous lines of the stack point to the constructor of MovieClip and then to a mysterious constructChildren() method of Sprite
That happens to be an internal method used to create the childs of the Sprite that you might have setup on your clip's stage directly from Animate.
So my guess is, the player is trying to instantiate a symbol that extends Hock and that you positioned on the stage somewhere, and of course is doing it by passing zero arguments because that's what a normal Sprite would expect.
Check your library to see what extends Hock and then see which one of those is placed in some other symbol's stage. Your options then will be to remove that and create it from code or to rework the class signature to take zero arguments.
I came through DART custom elements, from dartlang.org site, here and here.
If I understood correctly,this is a vanilla DART custom element, not related to Polymer custom tags.
I wrote the below code,
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom');
CustomElement.created() : super.created() {
print('CustomElement created!');
}
}
void main() {
document.registerElement('x-custom', CustomElement);
}
and got the "CustomElement created!" statement printed in the console, which means the element had been created!
my question is, what else? how can I use this customs element, and what can I do with it can I write HTML template, if yes, how?
I read this but unfortunately could not how to do same with DART.
any thoughts!
This is also used by Polymer. Polymer is just the combination of Custom Element, HTML Imports, Template, Polymer, Polyfills and some builerplate to connect these parts and provider a nice API.
If you want to reinvent the wheel you can go with CustomElement alone.
Change your main to
void main() {
document.registerElement('x-custom', CustomElement);
var elem = new Element.tag('x-element');
elem.appendText('x-element');
document.body.append(elem);
elem.onClick.listen((e) {
print('clicked');
});
}
and you can react to click events
I was ableto write the below, which had been worked, feel I did it the long way,
I could not use the tag
Not sure if the way I used to callback the elements in the custumElement in the correct way, as I was forced to use .append for all the items, and not sure if there is an easier way to do it.
my index.html file is
pick a color:<input type="color" name="colorname" id="colorname"> the color you selected is: <output id="picked-color"></output> click it !
<div id='my-element'></div>
my index.dart file is:
import 'dart:html';
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom');
CustomElement.created() : super.created() { }
Element launchElement(Element o1){
o1.onClick.listen((e) => window.alert('the input color is: ${o1.text}'));
print('CustomElement created!');
var output = new Element.html('<div></div>');
var statement = new Element.html('<div></div>');
var bind = new Element.html('<div></div>')
..text='this text will be dynamically replaced by what you are entering down';
var input = new InputElement()
..id ='input'
..type ='text'
..placeholder='enter data here';
input.onInput.listen((e) => bind.text=input.value);
var element = new Element.html('<span>content: </span>')
..style.color='red';
var button = new ButtonElement()
..id = 'awesome'
..classes.add('important')
..onClick.listen((e) => pop(input.value)) // "Hi There!!!")
..text = 'Click Me man!'
..style.color='orange';
statement.innerHtml="<b>I'm an x-custom-with-markup!</b> ";
output.node..add(statement)..add(bind)..add(input)..add(element)..add(button);
return (output);
}
var button1 = new ButtonElement()
..id = 'awesome2'
..text = 'External Click Me man!';
void pop(i){ window.alert("input is: $i"); }
}
void main() {
document.registerElement('x-custom', CustomElement);
var xFoo = new Element.tag('x-custom');
InputElement colorname = querySelector('#colorname');
Element theColor = querySelector('#picked-color');
xFoo = xFoo.launchElement(theColor);
theColor.text = colorname.value;
Element myDiv=querySelector('#my-element');
myDiv.children.add(xFoo);
colorname.onInput.listen((Event e) {
theColor.text = colorname.value;
});
}
Not available now
document.registerElement is deprecated: https://developer.mozilla.org/zh-CN/docs/Web/API/Document/registerElement
window.customElements.define with Dart is blocked by https://github.com/dart-lang/sdk/issues/35829
The below code is to extract parameter from URL using dart
I am able to print the values in console but i am not able to get how to display the output in console to browser that is html version. Please help
import 'dart:core';
import 'dart:html';
void main() {
var q = '?id=abc&id1=cde&id3=asad';
if(q.contains('?')) {
var a = q.replaceFirst("?"," ");
var c = a.split("&");
print(c);
}
You can add the output to the body element or you add an element like a <div></div> and insert it inside this element.
To use a 'div' element you should add an element in you index.html (or whatever name you have for your HTML page) like
...
<body>
<div id='someDiv'></div>
</body>
in your Dart code you do it like
import 'dart:core';
import 'dart:html';
void main() {
var q = '?id=abc&id1=cde&id3=asad';
if(q.contains('?')) {
var a = q.replaceFirst("?"," ");
var c = a.split("&");
// querySelector('#someDiv').text = '${c}'; // <= you may need some encoding for special characters like <, >, &, ...
var div = querySelector('#someDiv');
c.forEach((e) => div.append(new DivElement()..text = '${e}'));
}