Followup 248ac9e: set $wgAutoloadClasses to an array after declaring
[mediawiki.git] / resources / src / mediawiki.page / mediawiki.page.gallery.js
blob1892967a338ffe69355059735e865ae73c444478
1 /*!
2  * Show gallery captions when focused. Copied directly from jquery.mw-jump.js.
3  * Also Dynamically resize images to justify them.
4  */
5 ( function ( $ ) {
6         $( function () {
7                 var isTouchScreen,
8                         gettingFocus,
9                         galleries = 'ul.mw-gallery-packed-overlay, ul.mw-gallery-packed-hover, ul.mw-gallery-packed';
11                 // Is there a better way to detect a touchscreen? Current check taken from stack overflow.
12                 isTouchScreen = !!( window.ontouchstart !== undefined || window.DocumentTouch !== undefined && document instanceof window.DocumentTouch );
14                 if ( isTouchScreen ) {
15                         // Always show the caption for a touch screen.
16                         $( 'ul.mw-gallery-packed-hover' )
17                                 .addClass( 'mw-gallery-packed-overlay' )
18                                 .removeClass( 'mw-gallery-packed-hover' );
19                 } else {
20                         // Note use of just "a", not a.image, since we want this to trigger if a link in
21                         // the caption receives focus
22                         $( 'ul.mw-gallery-packed-hover li.gallerybox' ).on( 'focus blur', 'a', function ( e ) {
23                                 // Confusingly jQuery leaves e.type as focusout for delegated blur events
24                                 gettingFocus = e.type !== 'blur' && e.type !== 'focusout';
25                                 $( this ).closest( 'li.gallerybox' ).toggleClass( 'mw-gallery-focused', gettingFocus );
26                         } );
27                 }
29                 // Now on to justification.
30                 // We may still get ragged edges if someone resizes their window. Could bind to
31                 // that event, otoh do we really want to constantly be resizing galleries?
32                 $( galleries ).each( function () {
33                         var lastTop,
34                                 $img,
35                                 imgWidth,
36                                 imgHeight,
37                                 rows = [],
38                                 $gallery = $( this );
40                         $gallery.children( 'li' ).each( function () {
41                                 // Math.floor to be paranoid if things are off by 0.00000000001
42                                 var top = Math.floor( $( this ).position().top ),
43                                         $this = $( this );
45                                 if ( top !== lastTop ) {
46                                         rows[rows.length] = [];
47                                         lastTop = top;
48                                 }
50                                 $img = $this.find( 'div.thumb a.image img' );
51                                 if ( $img.length && $img[0].height ) {
52                                         imgHeight = $img[0].height;
53                                         imgWidth = $img[0].width;
54                                 } else {
55                                         // If we don't have a real image, get the containing divs width/height.
56                                         // Note that if we do have a real image, using this method will generally
57                                         // give the same answer, but can be different in the case of a very
58                                         // narrow image where extra padding is added.
59                                         imgHeight = $this.children().children( 'div:first' ).height();
60                                         imgWidth = $this.children().children( 'div:first' ).width();
61                                 }
63                                 // Hack to make an edge case work ok
64                                 if ( imgHeight < 30 ) {
65                                         // Don't try and resize this item.
66                                         imgHeight = 0;
67                                 }
69                                 rows[rows.length - 1][rows[rows.length - 1].length] = {
70                                         $elm: $this,
71                                         width: $this.outerWidth(),
72                                         imgWidth: imgWidth,
73                                         // XXX: can divide by 0 ever happen?
74                                         aspect: imgWidth / imgHeight,
75                                         captionWidth: $this.children().children( 'div.gallerytextwrapper' ).width(),
76                                         height: imgHeight
77                                 };
78                         } );
80                         ( function () {
81                                 var maxWidth,
82                                         combinedAspect,
83                                         combinedPadding,
84                                         curRow,
85                                         curRowHeight,
86                                         wantedWidth,
87                                         preferredHeight,
88                                         newWidth,
89                                         padding,
90                                         $outerDiv,
91                                         $innerDiv,
92                                         $imageDiv,
93                                         $imageElm,
94                                         imageElm,
95                                         $caption,
96                                         i,
97                                         j,
98                                         avgZoom,
99                                         totalZoom = 0;
101                                 for ( i = 0; i < rows.length; i++ ) {
102                                         maxWidth = $gallery.width();
103                                         combinedAspect = 0;
104                                         combinedPadding = 0;
105                                         curRow = rows[i];
106                                         curRowHeight = 0;
108                                         for ( j = 0; j < curRow.length; j++ ) {
109                                                 if ( curRowHeight === 0 ) {
110                                                         if ( isFinite( curRow[j].height ) ) {
111                                                                 // Get the height of this row, by taking the first
112                                                                 // non-out of bounds height
113                                                                 curRowHeight = curRow[j].height;
114                                                         }
115                                                 }
117                                                 if ( curRow[j].aspect === 0 || !isFinite( curRow[j].aspect ) ) {
118                                                         // One of the dimensions are 0. Probably should
119                                                         // not try to resize.
120                                                         combinedPadding += curRow[j].width;
121                                                 } else {
122                                                         combinedAspect += curRow[j].aspect;
123                                                         combinedPadding += curRow[j].width - curRow[j].imgWidth;
124                                                 }
125                                         }
127                                         // Add some padding for inter-element spacing.
128                                         combinedPadding += 5 * curRow.length;
129                                         wantedWidth = maxWidth - combinedPadding;
130                                         preferredHeight = wantedWidth / combinedAspect;
132                                         if ( preferredHeight > curRowHeight * 1.5 ) {
133                                                 // Only expand at most 1.5 times current size
134                                                 // As that's as high a resolution as we have.
135                                                 // Also on the off chance there is a bug in this
136                                                 // code, would prevent accidentally expanding to
137                                                 // be 10 billion pixels wide.
138                                                 if ( i === rows.length - 1 ) {
139                                                         // If its the last row, and we can't fit it,
140                                                         // don't make the entire row huge.
141                                                         avgZoom = ( totalZoom / ( rows.length - 1 ) ) * curRowHeight;
142                                                         if ( isFinite( avgZoom ) && avgZoom >= 1 && avgZoom <= 1.5 ) {
143                                                                 preferredHeight = avgZoom;
144                                                         } else {
145                                                                 // Probably a single row gallery
146                                                                 preferredHeight = curRowHeight;
147                                                         }
148                                                 } else {
149                                                         preferredHeight = 1.5 * curRowHeight;
150                                                 }
151                                         }
152                                         if ( !isFinite( preferredHeight ) ) {
153                                                 // This *definitely* should not happen.
154                                                 // Skip this row.
155                                                 continue;
156                                         }
157                                         if ( preferredHeight < 5 ) {
158                                                 // Well something clearly went wrong...
159                                                 // Skip this row.
160                                                 continue;
161                                         }
163                                         if ( preferredHeight / curRowHeight > 1 ) {
164                                                 totalZoom += preferredHeight / curRowHeight;
165                                         } else {
166                                                 // If we shrink, still consider that a zoom of 1
167                                                 totalZoom += 1;
168                                         }
170                                         for ( j = 0; j < curRow.length; j++ ) {
171                                                 newWidth = preferredHeight * curRow[j].aspect;
172                                                 padding = curRow[j].width - curRow[j].imgWidth;
173                                                 $outerDiv = curRow[j].$elm;
174                                                 $innerDiv = $outerDiv.children( 'div' ).first();
175                                                 $imageDiv = $innerDiv.children( 'div.thumb' );
176                                                 $imageElm = $imageDiv.find( 'img' ).first();
177                                                 imageElm = $imageElm.length ? $imageElm[0] : null;
178                                                 $caption = $outerDiv.find( 'div.gallerytextwrapper' );
180                                                 // Since we are going to re-adjust the height, the vertical
181                                                 // centering margins need to be reset.
182                                                 $imageDiv.children( 'div' ).css( 'margin', '0px auto' );
184                                                 if ( newWidth < 60 || !isFinite( newWidth ) ) {
185                                                         // Making something skinnier than this will mess up captions,
186                                                         if ( newWidth < 1 || !isFinite( newWidth ) ) {
187                                                                 $innerDiv.height( preferredHeight );
188                                                                 // Don't even try and touch the image size if it could mean
189                                                                 // making it disappear.
190                                                                 continue;
191                                                         }
192                                                 } else {
193                                                         $outerDiv.width( newWidth + padding );
194                                                         $innerDiv.width( newWidth + padding );
195                                                         $imageDiv.width( newWidth );
196                                                         $caption.width( curRow[j].captionWidth + ( newWidth - curRow[j].imgWidth ) );
197                                                 }
199                                                 if ( imageElm ) {
200                                                         // We don't always have an img, e.g. in the case of an invalid file.
201                                                         imageElm.width = newWidth;
202                                                         imageElm.height = preferredHeight;
203                                                 } else {
204                                                         // Not a file box.
205                                                         $imageDiv.height( preferredHeight );
206                                                 }
207                                         }
208                                 }
209                         }() );
210                 } );
211         } );
212 }( jQuery ) );