11import Backbone from 'backbone' ;
22import Adapt from 'core/js/adapt' ;
3- import helpers from './helpers' ;
4-
5- const computeAccesibleName = helpers . computeAccesibleName ;
6- const computeAccessibleDescription = helpers . computeAccessibleDescription ;
7- const getAnnotationPosition = helpers . getAnnotationPosition ;
3+ import {
4+ HEADING_SELECTOR ,
5+ computeAccessibleName ,
6+ computeAccessibleDescription ,
7+ getAnnotationPosition ,
8+ getContainer ,
9+ shouldAnnotate
10+ } from './helpers' ;
811
912class Annotation extends Backbone . View {
1013
14+ events ( ) {
15+ return {
16+ click : 'onClick'
17+ } ;
18+ }
19+
20+ onClick ( event ) {
21+ console . log ( 'Annotation clicked for' , this . $parent [ 0 ] ) ;
22+ }
23+
1124 className ( ) {
1225 return 'devtools__annotation' ;
1326 }
@@ -18,21 +31,27 @@ class Annotation extends Backbone.View {
1831
1932 initialize ( options ) {
2033 this . $parent = options . $parent ;
34+ this . $container = getContainer ( this . $parent ) ;
2135 this . allowText = options . allowText ;
2236 this . $el . data ( 'annotating' , this . $parent ) ;
2337 this . $el . data ( 'view' , this ) ;
2438 }
2539
2640 render ( ) {
41+ function hash ( name , description , position ) {
42+ return name + description + position . className + position . css . top + position . css . left ;
43+ }
2744 const template = Handlebars . templates . devtoolsAnnotation ;
28- const name = computeAccesibleName ( this . $parent , this . allowText ) ;
45+ const name = computeAccessibleName ( this . $parent , this . allowText ) ;
2946 const description = computeAccessibleDescription ( this . $parent ) ;
30- this . $el . html ( template ( { name, description } ) ) ;
31- if ( ! name ) this . $el . addClass ( 'has-annotation-warning' ) ;
3247 const position = getAnnotationPosition ( this . $parent , this . $el ) ;
48+ if ( this . _last === hash ( name , description , position ) ) return ;
49+ this . $el . html ( template ( { name, description } ) ) ;
50+ this . $el . toggleClass ( 'has-annotation-warning' , ! name ) ;
3351 this . $el . css ( position . css ) ;
3452 this . $el . removeClass ( 'is-top is-left is-right is-bottom is-contained' ) ;
3553 this . $el . addClass ( position . className ) ;
54+ this . _last = hash ( name , description , position ) ;
3655 }
3756
3857 showOutline ( ) {
@@ -44,7 +63,6 @@ class Annotation extends Backbone.View {
4463 this . $parent . removeClass ( 'devtools__annotation-outline' ) ;
4564 this . $el . removeClass ( 'has-mouse-over' ) ;
4665 }
47-
4866}
4967
5068class AltText extends Backbone . Controller {
@@ -57,14 +75,10 @@ class AltText extends Backbone.Controller {
5775 onEnabled ( ) {
5876 if ( ! Adapt . devtools . get ( '_isEnabled' ) ) return ;
5977 _ . bindAll ( this , 'onDomMutation' , 'render' , 'onMouseOver' ) ;
60- this . mutations = [ ] ;
6178 this . mutated = false ;
6279 this . listenTo ( Adapt . devtools , 'change:_altTextEnabled' , this . toggleAltText ) ;
6380 $ ( 'body' ) . append ( $ ( '<div class="devtools__annotations" aria-hidden="true"></div>' ) ) ;
64- // if available we can use to avoid unnecessary checks
65- if ( typeof MutationObserver === 'function' ) {
66- this . observer = new MutationObserver ( this . onDomMutation ) ;
67- }
81+ this . observer = new MutationObserver ( this . onDomMutation ) ;
6882 }
6983
7084 connectObserver ( ) {
@@ -89,10 +103,11 @@ class AltText extends Backbone.Controller {
89103 } ) ;
90104 }
91105 this . listenTo ( Adapt , {
92- 'popup:closed notify:closed drawer:closed' : this . onDomMutation ,
93106 remove : this . removeAllAnnotations
94107 } ) ;
95108 $ ( window ) . on ( 'scroll' , this . onDomMutation ) ;
109+ $ ( document ) . on ( 'transitionend' , this . onDomMutation ) ;
110+ $ ( document ) . on ( 'animationend' , this . onDomMutation ) ;
96111 $ ( document ) . on ( 'mouseover' , '*' , this . onMouseOver ) ;
97112 }
98113
@@ -124,8 +139,10 @@ class AltText extends Backbone.Controller {
124139 if ( this . observer ) {
125140 this . observer . disconnect ( ) ;
126141 }
127- this . stopListening ( Adapt , 'popup:closed notify:closed drawer:closed ' , this . onDomMutation ) ;
142+ this . stopListening ( Adapt , 'remove ' , this . removeAllAnnotations ) ;
128143 $ ( window ) . off ( 'scroll' , this . onDomMutation ) ;
144+ $ ( document ) . off ( 'transitionend' , this . onDomMutation ) ;
145+ $ ( document ) . off ( 'animationend' , this . onDomMutation ) ;
129146 $ ( document ) . off ( 'mouseover' , '*' , this . onMouseOver ) ;
130147 }
131148
@@ -141,8 +158,13 @@ class AltText extends Backbone.Controller {
141158 }
142159
143160 addAnnotation ( $element , allowText ) {
144- const annotation = new Annotation ( { $parent : $element , allowText } ) ;
145- $ ( '.devtools__annotations' ) . append ( annotation . $el ) ;
161+ const annotation = new Annotation ( {
162+ $parent : $element ,
163+ allowText
164+ } ) ;
165+
166+ annotation . $container . append ( annotation . $el ) ;
167+
146168 $element . data ( 'annotation' , annotation ) ;
147169 $element . attr ( 'data-annotated' , true ) ;
148170 this . updateAnnotation ( $element , annotation , allowText ) ;
@@ -170,9 +192,7 @@ class AltText extends Backbone.Controller {
170192 const $element = $annotation . data ( 'annotating' ) ;
171193 const annotation = $annotation . data ( 'view' ) ;
172194 if ( ! $element ) return ;
173- const isOutOfDom = ( $element . parents ( 'html' ) . length === 0 ) ;
174- const isHeadingHeightZero = $element . is ( 'h1,h2,h3,h4,h5,h6,h7,[role=heading]' ) && $element . height ( ) === 0 ;
175- if ( ! isOutOfDom && ( $element . onscreen ( ) . onscreen || isHeadingHeightZero ) ) return ;
195+ if ( shouldAnnotate ( $element ) ) return ;
176196 this . removeAnnotation ( $element , annotation ) ;
177197 } ) ;
178198 }
@@ -181,7 +201,7 @@ class AltText extends Backbone.Controller {
181201 annotation . render ( ) ;
182202 }
183203
184- onDomMutation ( mutations ) {
204+ onDomMutation ( ) {
185205 if ( this . mutated ) return ;
186206 requestAnimationFrame ( this . render ) ;
187207 this . mutated = true ;
@@ -190,7 +210,7 @@ class AltText extends Backbone.Controller {
190210 render ( ) {
191211 if ( this . mutated === false ) return ;
192212 this . clearUpAnnotations ( ) ;
193- const $headings = $ ( 'h1,h2,h3,h4,h5,h6,h7,[role=heading]' ) ;
213+ const $headings = $ ( HEADING_SELECTOR ) ;
194214 const $labelled = $ ( [
195215 '.aria-label' ,
196216 '[alt]' ,
@@ -209,15 +229,8 @@ class AltText extends Backbone.Controller {
209229 . each ( ( index , element ) => {
210230 const $element = $ ( element ) ;
211231 const annotation = $element . data ( 'annotation' ) ;
212- const isVisible = $element . onscreen ( ) . onscreen ;
213- const isParentAriaHidden = Boolean ( $element . parents ( ) . filter ( '[aria-hidden=true]' ) . length ) ;
214- const isAriaHidden = Boolean ( $element . filter ( '[aria-hidden=true]' ) . length ) ;
215- const isNotAriaHidden = Boolean ( $element . filter ( '[aria-hidden=false]' ) . length ) ;
216- const isImg = $element . is ( 'img' ) ;
217- const allowText = $element . is ( '.aria-label,h1,h2,h3,h4,h5,h6,h7,[role=heading]' ) ;
218- const isOutOfDom = ( $element . parents ( 'html' ) . length === 0 ) ;
219- const isHeadingHeightZero = $element . is ( 'h1,h2,h3,h4,h5,h6,h7,[role=heading]' ) && $element . height ( ) === 0 ;
220- if ( ! isOutOfDom && ( isVisible || isHeadingHeightZero ) && ( isNotAriaHidden || ( ! isAriaHidden && ! isParentAriaHidden ) || ( isImg && ! isParentAriaHidden ) ) ) {
232+ const allowText = $element . is ( `.aria-label,${ HEADING_SELECTOR } ` ) ;
233+ if ( shouldAnnotate ( $element ) ) {
221234 if ( ! annotation ) this . addAnnotation ( $element , allowText ) ;
222235 else this . updateAnnotation ( $element , annotation , allowText ) ;
223236 } else if ( annotation ) {
0 commit comments