Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
- Added `childNodesAsList` to `Node` and `childrenAsList` to `Element` via
extensions to support mutable operations on node lists.
- Added `asList` to `NodeList` via extension.
- Added `data` to `HTMLElement`, `SVGElement` and `MathMLElement` via
extension. It provides nullable interface for `dataset` allowing to check if
data attribute is set.

## 1.1.1

Expand Down
1 change: 1 addition & 0 deletions web/lib/src/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
library;

export 'helpers/cross_origin.dart' show CrossOriginLocation, CrossOriginWindow;
export 'helpers/dataset.dart';
export 'helpers/enums.dart';
export 'helpers/events/events.dart';
export 'helpers/events/providers.dart';
Expand Down
51 changes: 51 additions & 0 deletions web/lib/src/helpers/dataset.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
Comment thread
fsw marked this conversation as resolved.
Outdated
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:js_interop';
import 'dart:js_interop_unsafe';

import '../dom/html.dart';
import '../dom/mathml_core.dart';
import '../dom/svg.dart';

/// Provides nullable api on `DOMStringMap`.
/// Native `DOMStringMap` returns non nullable `DOMString` from getter and
/// returns `undefined` when given key does not exist. As in Dart there is no
/// `undefined`, this wrapper will return null in such case.
/// This extension also allows removing `dataset` elements.
extension type NullableDOMStringMap._(JSObject _) implements JSObject {
/// Retrieves `dataset` element.
/// When it is not set (`data-*` attribute is missing) returns null.
Comment thread
fsw marked this conversation as resolved.
Outdated
external String? operator [](String name);

external void operator []=(
String name,
String value,
Comment thread
fsw marked this conversation as resolved.
Outdated
);

/// Removes `dataset` element (and corresponding `data-*` attribute)
String? remove(String name) {
final ret = this[name];
delete(name.toJS);
return ret;
}
}

Comment thread
fsw marked this conversation as resolved.
extension HTMLElementDatasetExtension on HTMLElement {
/// Wrapper for nullable [dataset]. See [NullableDOMStringMap] for details.
@JS('dataset')
external NullableDOMStringMap get data;
}

extension SVGElementDatasetExtension on SVGElement {
/// Wrapper for nullable [dataset]. See [NullableDOMStringMap] for details.
@JS('dataset')
external NullableDOMStringMap get data;
}

extension MathMLElementDatasetExtension on MathMLElement {
/// Wrapper for nullable [dataset]. See [NullableDOMStringMap] for details.
@JS('dataset')
external NullableDOMStringMap get data;
}
29 changes: 29 additions & 0 deletions web/test/helpers_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,33 @@ void main() {
test('Uri.toJS throws an ArgumentError for a relative URL', () {
expect(() => Uri.parse('/path').toJS, throwsArgumentError);
});

test('nullable dataset extension', () {
final elements = [SVGSVGElement(), HTMLDivElement(), MathMLElement.mi()];

for (var element in elements) {
element.setAttribute('data-foo', 'bar');
element.setAttribute('data-foo-camel', 'bar');
final data = element.isA<SVGElement>()
? (element as SVGElement).data
: element.isA<MathMLElement>()
? (element as MathMLElement).data
: (element as HTMLElement).data;
//read existing and not existing data
expect(data['foo'], equals('bar'));
expect(data['fooCamel'], equals('bar'));
expect(data['nonexisting'], isNull);

//update data
data['foo'] = data['fooCamel'] = 'bar2';
expect(data['foo'], equals('bar2'));
expect(data['fooCamel'], equals('bar2'));

//unset data
expect(data.remove('foo'), equals('bar2'));
expect(data.remove('fooCamel'), equals('bar2'));
expect(data['foo'], isNull);
expect(element.getAttribute('data-foo-camel'), isNull);
}
});
Comment thread
fsw marked this conversation as resolved.
}