33// BSD-style license that can be found in the LICENSE file.
44
55import 'dart:async' ;
6- // TODO: migrate to package:web
7- // ignore: deprecated_member_use
8- import 'dart:html' ;
6+ import 'dart:js_interop_unsafe' ;
97
108import 'package:_pub_shared/format/x_ago_format.dart' ;
9+ import 'package:web/web.dart' ;
10+ import 'package:web_app/src/web_util.dart' ;
1111
1212void setupHoverable () {
1313 _setEventForHoverable ();
@@ -29,15 +29,15 @@ Element? _activeHover;
2929/// Their `:hover` and `.hover` style must match to have the same effect.
3030void _setEventForHoverable () {
3131 document.body! .onClick.listen (deactivateHover);
32- for (final h in document.querySelectorAll ('.hoverable' )) {
32+ for (final h in document.querySelectorAll ('.hoverable' ). toElementList () ) {
3333 registerHoverable (h);
3434 }
3535}
3636
3737/// Deactivates the active hover (hiding the hovering panel).
3838void deactivateHover (_) {
3939 if (_activeHover case final activeHoverElement? ) {
40- activeHoverElement.classes .remove ('hover' );
40+ activeHoverElement.classList .remove ('hover' );
4141 _activeHover = null ;
4242 }
4343}
@@ -48,7 +48,7 @@ void registerHoverable(Element h) {
4848 if (h != _activeHover) {
4949 deactivateHover (e);
5050 _activeHover = h;
51- h.classes .add ('hover' );
51+ h.classList .add ('hover' );
5252 e.stopPropagation ();
5353 }
5454 });
@@ -61,13 +61,15 @@ void registerHoverable(Element h) {
6161
6262void _setEventForPackageTitleCopyToClipboard () {
6363 final roots = document.querySelectorAll ('.pkg-page-title-copy' );
64- for (final root in roots) {
65- final icon = root.querySelector ('.pkg-page-title-copy-icon' );
64+ for (final root in roots.toList ().whereType <Element >()) {
65+ final icon =
66+ root.querySelector ('.pkg-page-title-copy-icon' ) as HTMLElement ? ;
6667 if (icon == null ) continue ;
6768 final feedback = root.querySelector ('.pkg-page-title-copy-feedback' );
6869 if (feedback == null ) continue ;
69- final copyContent = icon.dataset['copy-content' ];
70- if (copyContent == null || copyContent.isEmpty) continue ;
70+ if (! icon.dataset.has ('copyContent' )) continue ;
71+ final copyContent = icon.dataset['copyContent' ];
72+ if (copyContent.isEmpty) continue ;
7173 _setupCopyAndFeedbackButton (
7274 copy: icon,
7375 feedback: feedback,
@@ -77,23 +79,23 @@ void _setEventForPackageTitleCopyToClipboard() {
7779}
7880
7981Future <void > _animateCopyFeedback (Element feedback) async {
80- feedback.classes .add ('visible' );
82+ feedback.classList .add ('visible' );
8183 await window.animationFrame;
8284 await Future <void >.delayed (Duration (milliseconds: 1600 ));
83- feedback.classes .add ('fadeout' );
85+ feedback.classList .add ('fadeout' );
8486 await window.animationFrame;
8587 // NOTE: keep in sync with _variables.scss 0.9s animation with the key
8688 // $copy-feedback-transition-opacity-delay
8789 await Future <void >.delayed (Duration (milliseconds: 900 ));
8890 await window.animationFrame;
8991
90- feedback.classes
92+ feedback.classList
9193 ..remove ('visible' )
9294 ..remove ('fadeout' );
9395}
9496
9597void _copyToClipboard (String text) {
96- final ta = TextAreaElement ();
98+ final ta = HTMLTextAreaElement ();
9799 ta.value = text;
98100 document.body! .append (ta);
99101 ta.select ();
@@ -102,31 +104,43 @@ void _copyToClipboard(String text) {
102104}
103105
104106void _setEventForPreCodeCopyToClipboard () {
105- document.querySelectorAll ('.markdown-body pre' ).forEach ((pre) {
106- final container = DivElement ()..classes.add ('-pub-pre-copy-container' );
107+ final elements = document
108+ .querySelectorAll ('.markdown-body pre' )
109+ .toElementList <HTMLElement >();
110+ elements.forEach ((pre) {
111+ final container = HTMLDivElement ()
112+ ..classList.add ('-pub-pre-copy-container' );
107113 pre.replaceWith (container);
108114 container.append (pre);
109115
110- final button = DivElement ()
111- ..classes .addAll (['-pub-pre-copy-button' , 'filter-invert-on-dark' ])
116+ final button = HTMLDivElement ()
117+ ..classList .addAll (['-pub-pre-copy-button' , 'filter-invert-on-dark' ])
112118 ..setAttribute ('title' , 'copy to clipboard' );
113119 container.append (button);
114120
115- final feedback = DivElement ()
116- ..classes .add ('-pub-pre-copy-feedback' )
121+ final feedback = HTMLDivElement ()
122+ ..classList .add ('-pub-pre-copy-feedback' )
117123 ..text = 'copied to clipboard' ;
118124 container.append (feedback);
119125
120126 _setupCopyAndFeedbackButton (
121127 copy: button,
122128 feedback: feedback,
123- textFn: () => pre.dataset['textToCopy' ]? .trim () ?? pre.text! .trim (),
129+ textFn: () {
130+ if (pre.dataset.has ('textToCopy' )) {
131+ final text = pre.dataset['textToCopy' ].trim ();
132+ if (text.isNotEmpty) {
133+ return text;
134+ }
135+ }
136+ return pre.textContent? .trim () ?? '' ;
137+ },
124138 );
125139 });
126140}
127141
128142void _setupCopyAndFeedbackButton ({
129- required Element copy,
143+ required HTMLElement copy,
130144 required Element feedback,
131145 required String Function () textFn,
132146}) {
@@ -151,7 +165,7 @@ void _setupCopyAndFeedbackButton({
151165
152166// Update x-ago labels at load time in case the page was stale in the cache.
153167void _updateXAgoLabels () {
154- document.querySelectorAll ('a.-x-ago' ).forEach ((e) {
168+ document.querySelectorAll ('a.-x-ago' ).toElementList (). forEach ((e) {
155169 final timestampMillisAttr = e.getAttribute ('data-timestamp' );
156170 final timestampMillisValue =
157171 timestampMillisAttr == null ? null : int .tryParse (timestampMillisAttr);
@@ -160,7 +174,7 @@ void _updateXAgoLabels() {
160174 }
161175 final timestamp = DateTime .fromMillisecondsSinceEpoch (timestampMillisValue);
162176 final newLabel = formatXAgo (DateTime .now ().difference (timestamp));
163- final oldLabel = e.text ;
177+ final oldLabel = e.textContent ;
164178 if (oldLabel != newLabel) {
165179 e.text = newLabel;
166180 }
@@ -169,12 +183,12 @@ void _updateXAgoLabels() {
169183
170184// Bind click events to switch between the title and the label on x-ago blocks.
171185void _setEventForXAgo () {
172- document.querySelectorAll ('a.-x-ago' ).forEach ((e) {
186+ document.querySelectorAll ('a.-x-ago' ).toElementList (). forEach ((e) {
173187 e.onClick.listen ((event) {
174188 event.preventDefault ();
175189 event.stopPropagation ();
176- final text = e.text ;
177- e.text = e.getAttribute ('title' );
190+ final text = e.textContent ;
191+ e.text = e.getAttribute ('title' ) ?? '' ;
178192 e.setAttribute ('title' , text! );
179193 });
180194 });
0 commit comments